简体   繁体   中英

Why React state is different from Redux State

I'm new to Redux + React and Im facing a problem that it's getting me crazy.

Update: Added Git repo instead of pasting here all the code

I'm creating a simple darts scoreboard and saving everything on the redux store. The problem is that when I try to access the data from a render method is not there. Is like state not being propagated to props.

But if I check redux developments tools the data is there. Some screenshots to clarify, where you can see that while in Redux all shots are there on React only the first shot appear. 所有照片的Redux商店 反应状态丢失的镜头

I thought that could be due to my reducers not using inmutable data but I think they are all ok. Code Im using below:

import update from 'react-addons-update';

function players(state = [], action) {

  switch( action.type ){

    case 'ADD_USER_TO_GAME':
        return [
            ...state,
            action.user
        ];
    case 'REORDER_USERS':
      return action.sortedArray;

    case 'REMOVE_USER':
      return [
        ...state.slice( 0, action.index ),
        ...state.slice( action.index + 1 ),
      ];

    case 'SET_ALL_SCORE':
      let new_state = [...state];
      for( let player in new_state ){
          if( new_state[player].ID ) {
              new_state[player].score = action.user_score;
              new_state[player].shots = [];      
          }
      }
      return new_state;

    case 'SAVE_SHOT':
      return [
        ...state.slice( 0, action.user ),
        { ...state[action.user], shots: [...state[action.user].shots, action.shot] },
        ...state.slice( action.user + 1 ),
      ];

    case 'SAVE_SCORE':

      return [
        ...state.slice( 0, action.user ),
        { ...state[action.user], score: action.score },
        ...state.slice( action.user + 1 ),
      ];

    default:
        return state;
  }

}

export default players;

You're mutating your state directly here:

case 'SET_ALL_SCORE':
  let new_state = [...state];
  for( let player in new_state ){
      if( new_state[player].ID ) {
          new_state[player].score = action.user_score;
          new_state[player].shots = [];      
      }
  }
  return new_state;

You did clone the state object, but you're mutating it's members directly.

Like this:

case 'SET_ALL_SCORE':
  return state.map(player => (
    player.ID
      ? { ...player, score: action.user_score, shots: [] }
      : player
  ));

You are most likely not including the Provider from react-redux in your index.js file. The Provider gives you access to the store in each component. Check out the below example:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import rootReducer from './reducers/rootReducer'
import {createStore, applyMiddleware} from 'redux';
import reduxPromise from 'redux-promise';
import { Router, browserHistory } from 'react-router';
import Routes from './routes';


let storewithmiddleware = applyMiddleware(reduxPromise)(createStore)(rootReducer)

ReactDOM.render(
  <Provider store={storewithmiddleware}>
    <Router history={browserHistory} routes={Routes} />
  </Provider>,
  document.getElementById('root')
);

Additionally, you will want to mapStateToProps and subscribe the component to the store with connect() like this:

const WelcomePageContainer = connect(mapStateToProps, null)(WelcomePage)

function mapStateToProps(state) {
  return {currentUser: state.currentUser}
} 

(see here: http://redux.js.org/docs/basics/UsageWithReact.html )

It seems like you could really benefit from going through Dan Abramov's tutorials on Redux on egghead.io They are fantastic and clear. Also, do the code along tutorials--they give a great sense of how Redux layers on top of your React app.

Just to note: component state in React is not synonymous with the Redux store.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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