React Redux: Uncaught Invariant Violation (Objects are not valid as a React child) [英] React Redux: Uncaught Invariant Violation (Objects are not valid as a React child)

查看:38
本文介绍了React Redux: Uncaught Invariant Violation (Objects are not valid as a React child)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到的错误是react-dom.development.js:55 Uncaught Invariant Violation: Objects are not valid as a React child (found: object with keys {counter}).如果你打算渲染一个集合的孩子,请改用数组."

当我将 Counter.js<p>{this.state.counter}</p> 更改为 <p> 时会发生这种情况.{this.props.counter}</p>

根据我的理解,我正在使用 mapStateToProps 和 mapDispatchToProps,我应该能够至少拉出计数器的初始状态,即 0.

我不确定这是否是问题的原因,但我正在使用 console.log 查看状态,但不确定这是否正确:

{计数器:{…}}计数器:{计数器:0}__proto__:对象

Counter.js

//导入:依赖import React, { Component } from 'react';从'react-redux'导入{连接};//导入:操作类型从 '../actionTypes/index' 导入 { INCREASE_COUNTER, DECREASE_COUNTER };//组件:计数器类计数器扩展了 React.Component {构造函数(道具){超级(道具);this.state = {计数器:0,};}使成为() {返回 (<div><h2>React Redux 计数器</h2><button type="button" onClick={() =>this.props.increaseCounter()}>Increase</button><p>{this.props.counter}</p><button type="button" onClick={() =>this.props.decreaseCounter()}>Decrease</button>

);}}//将状态映射到道具(Reducers)const mapStateToProps = (状态) =>{console.log('状态:');控制台日志(状态);console.log('');返回 {计数器:state.counter,};};//将调度映射到道具(动作)const mapDispatchToProps = (调度) =>{返回 {增加计数器:() =>调度({ 类型:INCREASE_COUNTER }),减少计数器:() =>调度({ 类型:DECREASE_COUNTER }),};};//出口导出默认连接(mapStateToProps,mapDispatchToProps)(计数器);

App.js

//导入:依赖import React, { Component } from 'react';//进口:组件从'./components/Counter'导入计数器;//反应应用类 App 扩展组件 {使成为() {返回 (<div><计数器/>

);}}//出口导出默认应用程序;

index.js

//导入:依赖从反应"导入反应;从 'react-dom' 导入 ReactDOM;从'react-redux'导入{提供者};从 './store/store' 导入商店;//导入:反应应用程序从'./App'导入应用程序;//渲染应用ReactDOM.render(<提供者商店={商店}><应用程序/></提供者>,document.getElementById('app'),);

store.js

//导入:依赖import { createStore, applyMiddleware } from 'redux';从redux-thunk"导入 thunk;import { createLogger } from 'redux-logger';//导入:Redux从'../reducers/index'导入rootReducer;//Redux:Thunk(异步/等待)const 中间件 = [thunk];如果(process.env.NODE_ENV !=='生产'){middleware.push(createLogger());}//Redux:存储const store = createStore(根减速器,应用中间件(...中间件),);//出口导出默认商店;

counterReducer.js

import { INCREASE_COUNTER, DECREASE_COUNTER } from '../actionTypes/actionTypes';//初始状态常量初始状态 = {计数器:0,};//Redux:计数器减速器const counterReducer = (state = initialState, action) =>{开关(动作.类型){案例增加计数器:{返回 {...状态,计数器:state.counter + 1,};}案例减少计数器:{返回 {...状态,计数器:state.counter - 1,};}默认: {返回状态;}}};//出口导出默认 counterReducer;

actionTypes.js

export const INCREASE_COUNTER = 'INCREASE_COUNTER';export const DECREASE_COUNTER = 'DECREASE_COUNTER';

解决方案

您的状态结构如下:

{柜台: {计数器:0}}

它的结构是这样的,因为你的 counterReducer 定义了一个名为 counter 的嵌套字段,然后 counterReducer 被组合成一个更大的对象,因为它是传递给 combineReducers({counter : counterReducer}).

在您的组件中,您正在渲染:

{this.props.counter}

但是,props.counter 将是一个对象,例如 {counter : 0}.

React 不会让你只是将一个对象放入渲染输出 - 它不知道如何处理它.

如果只想显示计数器值,则需要:

{this.props.counter.counter}

另一种选择是将您的 mapStateToProps 更改为:

const mapStateToProps = (state) =>{返回 {计数器:state.counter.counter,};};

第三个选项是更改 counterReducer 以便它只跟踪数字本身作为 reducer 的 state 参数,而不是将该值嵌套在对象中.

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';

解决方案

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.

这篇关于React Redux: Uncaught Invariant Violation (Objects are not valid as a React child)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆