React Redux Store更新,但组件不重新渲染

时间:2017-01-31 17:49:28

标签: reactjs redux render react-redux

使用终端测试我的调度操作,Redux-logger显示我的状态正在正确更新。但是,由于状态更改,我的组件不会重新呈现。我已经查看了关于组件没有重新呈现的SO答案,大多数回复声称该州正在变异;因此,Redux不会重新渲染。但是,我使用Lodash的合并来深度复制一个对象,我很确定我没有返回一个修改过的对象。 (请参阅下面附带的片段)

很想听听你们的一些建议,把头发拉出来!



const usersReducer = (state = {}, action) => {
  Object.freeze(state); // avoid mutating state

  console.log(state); 
  // returns an empty object  
  let newState = merge({}, state);
  console.log(newState); 
  // returns my state with my dispatched action object inside  already???
  // newState for some reason already has new dispatched action
  switch (action.type) {
    case RECEIVE_USER:
      let newUser = {[action.user.id] = action.user};
      return merge(newUser, newUser);
    case RECEIVE_USERS:
      newState = {};
      action.users.forEach(user => {
        newState[user.id] = user;
      });
      return merge({}, newState);
    default:
      return state;
  }
};




反应容器组件



import { connect } from 'react-redux';
import { receiveUsers, receiveUser, refreshAll, requestUsers, requestUser } from '../../actions/user_actions';
import allUsers from '../../reducers/selectors';
import UserList from './user_list';

const mapStateToProps = (state) => ({
  users: allUsers(state), // allUsers (selector that takes the state specfically the user Object and returns an array of user Objects)
  state
});

const mapDispatchToProps = (dispatch) => ({
  requestUser: () => dispatch(requestUser()),
  requestUsers: () => dispatch(requestUsers()),
  receiveUsers: (users) => dispatch(receiveUsers(users)),
  receiveUser: (user) => dispatch(receiveUser(user)),
  refreshAll: (users) => dispatch(refreshAll(users))
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(UserList);




反应演示文稿



import React from 'react';

class UserList extends React.Component {
  render() {
    const { users, state } = this.props;

    const userItems = users.map((user, idx) => {
        return(<li key={idx}>{user.username}</li>);
    });

    return (
      <div>
        <ul>
          { userItems }
        </ul>
      </div>
    );
  }
}

export default UserList;
&#13;
&#13;
&#13;

React Store

&#13;
&#13;
import { createStore, applyMiddleware } from 'redux';
import createLogger from 'redux-logger';
import RootReducer from '../reducers/root_reducer';

const logger = createLogger();
const configureStore = (preloadedState = {}) => {
  return createStore(
    RootReducer, 
    preloadedState,
    applyMiddleware(logger));
};

// const configureStore = createStore(rootReducer, applyMiddleware(logger));

// oddly enough, when I have the store as a constant and not a function that returns the store constant, dispatching actions through the terminal will correctly update the state and rerender the component 

export default configureStore;
&#13;
&#13;
&#13;

反应选择器

&#13;
&#13;
const allUsers = ({ users }) => {
  return Object.keys(users).map(id => (
    users[id]
  ));
};

export default allUsers;
&#13;
&#13;
&#13;

6 个答案:

答案 0 :(得分:2)

从 prop 状态创建数组的新副本以重新渲染组件

render() {

const {allPost} = this.props;
//Use the spread operator to create a new copy of the array
const posts = [...allPost];

 const plansList = () => {
     return posts.length < 1 ? null : posts && <PlansList allPost={posts} 
   />;
 };

return (
  <>
    <Container className="mt-lg-5 pt-lg-5">
    {plansList()}
  </Container>
  </>
);
}

答案 1 :(得分:1)

在这种情况下的常见问题是使用非反应性操作来更改状态。例如,将concat()用于数组,而不是push()等。

答案 2 :(得分:0)

你的React组件是什么样的?您是使用内部状态还是使用道具来推送数据。通常我看到的问题是人们用Redux状态设置道具的内部状态。你应该将道具推向组件,它们将在更新时重新渲染。

另外,退房 https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en

看看道具是否真的在变化。

答案 3 :(得分:0)

我使用这个解决方案来做到这一点。 我将用户置于我的状态,并使用componentWillReceiveProps对任何更改进行更新。希望它有所帮助: - )

class UserList extends React.Component {
    constructor(props) {
       super(props);
       console.log(this.props);
       this.state = {
          users: props.users
       };
    }
    componentWillReceiveProps(nextProps) {
        if (this.props.users !== nextProps.users) {
            this.setState({
                users: nextProps.users,
            });
        }
    }

  render() {
    const { users } = this.state;

    const userItems = users.map((user, idx) => {
        return(<li key={idx}>{user.username}</li>);
    });

    return (
      <div>
        <ul>
          { userItems }
        </ul>
      </div>
    );
  }
}

export default UserList;

答案 4 :(得分:0)

我有一个类似的问题,以防万一有人偶然发现了这个问题,我需要克隆数组以重新渲染视图:

export const addFieldRow = () => (
    (dispatch: any, getState: any) => {
        const state = getState();
        const myArrayOfObjects = myArrayOfObjectsProp(state);
        const newObject = {
            key: "",
            value: "",
        };
        myArrayOfObjects.push(newObject);
        dispatch(addFieldRowAction({ myArrayOfObjects: [...myArrayOfObjects] })); <== here
    }
);

答案 5 :(得分:0)

我花了很多时间发现当使用超过 1 个 reducer(使用 combineReducers)时,你的 mapStateToProps 应该指向正确的 reducer 名称,例如< /p>

const mapStateToProps = state => ({
  someVar: state.yourReducerName.someVar,
  loading: state.yourReducerName.loading,
  error: state.yourReducerName.error
});