问题
The error I'm receiving is "react-dom.development.js:55 Uncaught Invariant Violation: Objects are not valid as a React child (found: object with keys {counter}). If you meant to render a collection of children, use an array instead."
It occurs when I change Counter.js from <p>{this.state.counter}</p>
to <p>{this.props.counter}</p>
From my understanding, I'm using the mapStateToProps and mapDispatchToProps and I should be able to pull at least the initialState of the counter, which is 0.
I'm not sure if this is the cause of the issue, but I'm using console.log to view what the state looks like, but not sure if that is correct:
{counter: {…}}
counter: {counter: 0}
__proto__: Object
Counter.js
// Imports: Dependencies
import React, { Component } from 'react';
import { connect } from 'react-redux';
// Imports: Action Types
import { INCREASE_COUNTER, DECREASE_COUNTER } from '../actionTypes/index';
// Component: Counter
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
counter: 0,
};
}
render() {
return (
<div>
<h2>React Redux Counter</h2>
<button type="button" onClick={() => this.props.increaseCounter()}>Increase</button>
<p>{this.props.counter}</p>
<button type="button" onClick={() => this.props.decreaseCounter()}>Decrease</button>
</div>
);
}
}
// Map State To Props (Reducers)
const mapStateToProps = (state) => {
console.log('State:');
console.log(state);
console.log('');
return {
counter: state.counter,
};
};
// Map Dispatch To Props (Actions)
const mapDispatchToProps = (dispatch) => {
return {
increaseCounter: () => dispatch({ type: INCREASE_COUNTER }),
decreaseCounter: () => dispatch({ type: DECREASE_COUNTER }),
};
};
// Exports
export default connect(mapStateToProps, mapDispatchToProps)(Counter);
App.js
// Imports: Dependencies
import React, { Component } from 'react';
// Imports: Components
import Counter from './components/Counter';
// React Application
class App extends Component {
render() {
return (
<div>
<Counter />
</div>
);
}
}
// Exports
export default App;
index.js
// Imports: Dependencies
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store/store';
// Imports: React Application
import App from './App';
// Render App
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('app'),
);
store.js
// Imports: Dependencies
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { createLogger } from 'redux-logger';
// Imports: Redux
import rootReducer from '../reducers/index';
// Redux: Thunk (Async/Await)
const middleware = [thunk];
if (process.env.NODE_ENV !== 'production') {
middleware.push(createLogger());
}
// Redux: Store
const store = createStore(
rootReducer,
applyMiddleware(...middleware),
);
// Exports
export default store;
counterReducer.js
import { INCREASE_COUNTER, DECREASE_COUNTER } from '../actionTypes/actionTypes';
// Initial State
const initialState = {
counter: 0,
};
// Redux: Counter Reducer
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case INCREASE_COUNTER: {
return {
...state,
counter: state.counter + 1,
};
}
case DECREASE_COUNTER: {
return {
...state,
counter: state.counter - 1,
};
}
default: {
return state;
}
}
};
// Exports
export default counterReducer;
actionTypes.js
export const INCREASE_COUNTER = 'INCREASE_COUNTER';
export const DECREASE_COUNTER = 'DECREASE_COUNTER';
回答1:
Your state is structured like this:
{
counter: {
counter : 0
}
}
It's structured this way because your counterReducer
defines a nested field called counter
, and the counterReducer
is then combined into a larger object because it's passed to combineReducers({counter : counterReducer})
.
In your component, you're rendering:
<p>{this.props.counter}</p>
But, props.counter
is going to be an object, like {counter : 0}
.
React won't let you just plop an object into the render output - it doesn't know what to do with it.
If you just want to show the counter value, then it needs to be:
<p>{this.props.counter.counter}</p>
Another option would be to change your mapStateToProps
to be:
const mapStateToProps = (state) => {
return {
counter: state.counter.counter,
};
};
The third option would be to change the counterReducer
so that it only tracks the number itself as the reducer's state
argument, rather than nesting that value in an object.
来源:https://stackoverflow.com/questions/54894612/react-redux-uncaught-invariant-violation-objects-are-not-valid-as-a-react-chil