Почему не срабатывает mapStateToProps?
Недавно начал работать с Redux, вроде все получалось. Сейчас делаю еще один компонент, добавил еще reducer'ы, action, затем вызвал combinedReducers, но по какой-то причине возникает ошибка: this.props.books is undefined. Попробовал вызывать console.log из mapStateToProps, я так понял, в него даже не заходит приложение. Что может быть не так?
import React, { Component } from 'react';
import { Spinner, Row, Col, Container } from 'reactstrap';
import store from '../store/Store';
import { connect } from 'react-redux';
import getBooks from '../actions/ContentActions';
export class Books extends Component {
constructor(props) {
super(props);
this.state = {
isFetching: true
}
this.fetchData = this.fetchData.bind(this);
}
async componentDidMount() {
await this.fetchData(); // Получаю книги из API, чтобы занести их в store
}
async fetchData() {
var data = {
first: 1,
last: 9
}
var response = await fetch('contentRequests/getBooksInRange', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
})
var result = await response.json();
store.dispatch(getBooks(result)); // Вызываю экшн, который добавляет в store массив books, который приходит в result
console.log(this.props);
this.setState({isFetching:false });
}
render() {
console.log(this.props);
if (this.state.isFetching) {
return (
<Spinner animation="grow" variant="dark" />
);
}
//На этом месте возникает ошибка
if (this.props.books !== null || this.props.books !== undefined) {
var bookTitles = this.props.books.map((b) => <div><b>{b.bookTitle} ({b.publishYear})</b></div>);
var bookAuthors = this.props.books.map((a) => <div>{a.authorName}</div>);
var bookDescription = this.props.books.map((d) => <div>{d.description}</div>);
var books = [];
for (var i = 0; i < this.props.books.length; i++) {
books.push(
<Col key={'book_' + i} md={4}>
{bookTitles[i]}
{bookAuthors[i]}
{bookDescription[i]}
</Col>);
}
return (
<Container>
<h1>Каталог книг</h1>
<Row>
{books}
</Row>
</Container>
);
}
}
}
const mapStateToProps = state => {
console.log(state.books.books); // ничего в консоль не выводится
return {
books: state.books.books
}
}
export default connect(mapStateToProps, { getBooks })(Books); // Нужно ли тут передавать action в аргумент?
Написал комментарии к коду, чтобы быстрее можно было понять, что происходит
Так же появляется ошибка: Can't perform a React state update on an unmounted component.
Reducer:
import { GET_BOOKS } from '../constants/ActionTypes';
export default function getBooksReducer(state = { books: [] }, action) {
switch (action.type) {
case GET_BOOKS:
return Object.assign({}, state,
{
books: action.books
});
default:
return state;
}
}
Action:
export const GET_BOOKS = 'GET_BOOKS';
export default function getBooks(books) {
return {
type: GET_BOOKS,
books: books
}
}
Combined:
import { combineReducers } from 'redux'
import getBooksReducer from './ContentReducers';
import loginAccountReducer from './AccountReducers';
export default combineReducers({
books: getBooksReducer,
account: loginAccountReducer
})
Store:
import { createStore } from 'redux';
import reducer from '../reducers/CombinedReducer';
const store = createStore(reducer);
export default store;
Ответы (1 шт):
store.dispatch(getBooks(result)) необходимо заменить на
this.props.getBooks(result)
так как action привязывается к dispatch в connect. Redux должен работать.
Код рендера книг можно написать проще через 1 map:
{this.props.books.map(({id, bookTitle, publishYear, authorName, description }) => {
return (
<Col key={id} md={4}>
<div>{bookTitle}{publishYear}</div>
<div>{authorName}</div>
<div>{description}</div>
</Col>
)
})}