简体   繁体   English

错误:在非常简单的Redux应用程序中,“对象作为React子对象无效”

[英]Error: 'Objects are not valid as a React child' in a very simple redux app

In this little Redux app i'm trying to make two very simple counters which can operate independently from each other. 在这个小的Redux应用程序中,我试图制作两个非常简单的计数器,它们可以彼此独立地运行。

At the moment only Counter1 is connected to the store: 目前,只有Counter1连接到商店:

const App = connect(mapStateToProps, mapDispatchToProps)(Counter1);

And store is made up from allReducers: 商店由allReducers组成:

const store = createStore(allReducers, composeEnchancers());

So, i'm getting this: 所以,我得到这个:

Uncaught Error: Objects are not valid as a React child (found: object with keys {CounterReducer1, CounterReducer2}). 未捕获的错误:对象作为React子对象无效(找到:带有键{CounterReducer1,CounterReducer2}的对象)。 If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. 如果您打算渲染孩子的集合,请改用数组或使用React附加组件中的createFragment(object)包装对象。 Check the render method of Counter1. 检查Counter1的渲染方法。

However if i make this: 但是,如果我这样做:

const store = createStore(CounterReducer1, composeEnchancers());

Everything starts to work fine... 一切开始正常...

I know that in this case mistake might be very stupid, but i still can't figure out where exactly is it hiding... 我知道在这种情况下,错误可能非常愚蠢,但是我仍然不知道它到底藏在什么地方...

Here is my entire code: 这是我的整个代码:

     import React from 'react';
     import ReactDOM from 'react-dom';
     import {createStore, bindActionCreators, compose, combineReducers} from 'redux';
     import {Provider, connect} from 'react-redux';




     //REDUCERS-----------------------------------------------------------------

     function CounterReducer1(state=1, action){
         switch(action.type){
         case 'INCREASE1': 
             return state=state+1;
         default: 
             return state;
         }

     }


     function CounterReducer2(state=1, action){
         switch(action.type){
         case 'INCREASE2': 
             return state=state+10;
         default: 
             return state;
         }

     }

     const allReducers = combineReducers({
         CounterReducer1,
         CounterReducer2
     });

     //REDUCERS------------------------------------------------------------------




     //COMPONENT COUNTER1--------------------------------------------------------
     const Counter1 = ({ counter1, BtnClickHandler1 }) => {
         return(
             <div>
                 <button onClick={() => BtnClickHandler1()}>Counter1Button</button>

                 <h2>{counter1}</h2>

             </div>
         );

     };
     //COMPONENT COUNTER1--------------------------------------------------------





     //COMPONENT COUNTER2--------------------------------------------------------
     const Counter2 = ({ counter2, BtnClickHandler2 }) => {
         return(
             <div>
                 <button onClick={() => BtnClickHandler2()}>Counter2Button</button>

                 <h2>{counter2}</h2>

             </div>
         );

     };
     //COMPONENT COUNTER2-------------------------------------------




     //ROOT COMPONENT-----------------------------------------------------------

     const RootComponent = () =>  {
         return (
             <div>
                 <Counter1 />
                 <Counter2 />
             </div>
         );
     };

     //ROOT COMPONENT--------------------------------------------------------




     //CONNECTING COUNTERS TO THE STORE-----------------------------

     const mapStateToProps = (state) => {
         return{
             counter1: state,
             counter2: state
         };
     };

     const mapDispatchToProps = (dispatch) => {
         return {
             BtnClickHandler1: () => dispatch({type: 'INCREASE1'}),
             BtnClickHandler2: () => dispatch({type: 'INCREASE2'})
         };
     };

     const App = connect(mapStateToProps, mapDispatchToProps)(Counter1);

     //CONNECTING COUNTERS TO THE STORE-----------------------------




     //STORE-------------------------------------------------------------------
     const composeEnchancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
     const store = createStore(allReducers, composeEnchancers());
     //STORE-------------------------------------------------------------------





     //RENDERING-----------------------------------------------------------------
     ReactDOM.render(

         <Provider store={store}>
             <App />
         </Provider>, 

         document.getElementById('app'));
     //RENDERING-----------------------------------------------------------------   

You're trying to pass the whole state (the result of combineReducers() ) to each component, which will result in having an object as props. 您试图将整个状态( combineReducers()的结果)传递给每个组件,这将导致有一个对象作为道具。 This is fine, of course, but it's not what you want in this case. 当然可以,但是这不是您想要的。 I'm talking about the following part of the code: 我正在谈论代码的以下部分:

return {
    counter1: state,
    counter2: state
};

If you'd do a console.log(state) right before returning, you would see this: 如果要在返回之前立即执行console.log(state) ,则会看到以下内容:

{CounterReducer1: 1, CounterReducer2: 1}

So in order to fix this, just return the appropriate part of the store to each component: 因此,为了解决此问题,只需将存储的适当部分返回给每个组件:

return {
    counter1: state.CounterReducer1,
    counter2: state.CounterReducer2
};

First and very important concept is you should not mutate state . 首先也是非常重要的概念是您不应该改变状态 Update your reducers as: 将减速器更新为:

function CounterReducer1(state=1, action){
     switch(action.type){
     case 'INCREASE1': 
         return state+1;
     default: 
         return state;
     }

 }


 function CounterReducer2(state=1, action){
     switch(action.type){
     case 'INCREASE2': 
         return state+10;
     default: 
         return state;
     }

 }
  1. You have only Counter1 component connected. 您仅连接了Counter1组件。 You can create just one container component that's connected and render multiple presentational components(Counter1 and Counter2). 您只能创建一个已连接的容器组件,并呈现多个演示组件(Counter1和Counter2)。 Move you mappings(mapStateToProps/mapDispatchToProps) and connect code in container component and you can pass the counter results as props to this presentational components. 移动您的映射(mapStateToProps / mapDispatchToProps)并在容器组件中连接代码,您就可以将计数器结果作为道具传递给此演示组件。

  2. When you combine reducers, if you dont provide any key, the reducer names which you provide are taken as keys. 合并化简器时,如果不提供任何键,则将您提供的化简器名称用作键。 In that case, you have to get the props as below: 在这种情况下,您必须获得以下道具:

return {
   counter1: state.CounterReducer1,
   counter2: state.CounterReducer2
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM