简体   繁体   中英

Updating redux state does not trigger re-render (nor does it update the state)

I'm pretty new to Redux and i'm encountering some problems with it.

I'm creating a list of items in a component, sending it to redux state and then i want to read from that redux state and display the items in a different list component.

The creation part works as i can console.log and getState() without problems (i am seeing the changes in Redux State).

My problem is that my component state does not change, nor does it re-render.

And now some code ->

this.state = {
    initialItems: this.props.SharepointItems,
}

And at the end

const mapStateToProps = (state) => {
    return {
        SharepointItems: state.listItems,
    }
}

export default connect(mapStateToProps)(SharePointList);

I even tried something like this in my componentDidMount() ->

    store.subscribe(() => {
        this.setState({ initialItems: this.props.SharepointItems });
        console.log("updating state");
    });

From what i've read i shouldnt need to update the state manually while using redux, or am i wrong?

EDIT: Since my list doesnt throw an error if i console.log i can see that the array is empty (which is what i defined in the Redux state). Is there something that i should be doing to get the new state ? Seems like its getting the immutable state or something like that (the empty array).

Edit2: Found the problem (or part of it). It appears as my state is 1 event behind. So redux contains the array with 4 items, the component state is empty. If i do a dispatch from the browser i get 5 items (as expected) in redux, but 4 in state (it finally shows not empty).

Also my code was a bit bugged (i was passing the entire array instead of items in the array).

I've changed it to

        result.map((item) => {
            store.dispatch(addListItem(item));
        });

And it started rendering. The problem is it displays items from 0 to 2 (4 in array), but the last one is left behind. Once again if i do another dispatch from the browser i get item 3 rendered, but 4 (the last one added) is only in redux state and does not update the list state.

Also...is it a good idea to do it like this? My list might have 1000 items in the future and i'm not sure that dispatch is a good solution (i need to make an API call to get the items first, which is why i'm using dispatch to populate redux).

Updated with reducer ->

const rootReducer = (state = initialState, action) => {
    switch (action.type) {
        case ADD_LISTITEM:
            return { ...state, listItems: [...state.listItems, action.payload] };
        case ADD_SPOTOKEN:
            return { ...state, spoToken: action.payload };
        default:
            return state;
    }
};

export default rootReducer;

Found something else thats a bit weird. I am also using React Router. As i said my list displays only 3 of the 4 items in my Redux State array. If i navigate to a different page and then back to the list page it actually renders all 4 of the items.

I believe your problem stems from the fact that you have "forked" SharepointItems off of props and set it to the component's local this.state . Unless you really need to, I'd recommend not doing that. Just use this.props . Dan Abramov (author of Redux) recommends this as a general principle too .

By forking props onto state, you create two sources of truth regarding the state of SharepointItems , namely, this.state.initialItems and this.props.SharepointItems . It then becomes your responsibility to keep this.state and this.props in sync by implementing componentDidUpdate (that is why you're not seeing it update). You can avoid all the extra work by just using the data that flows in from props .

The connect function will re-render your component with new props whenever you update the redux store. So in your render method, just refer to this.props.SharepointItems and not this.state.initialItems . Then you should be good to go, that is, assuming you've implemented your reducer(s) and store configuration properly.

I actually fixed this by mistake. I was planning on leaving it for the end and find a workaround for it, but i somehow fixed it.

I was importing the list component (which had the redux state props) in a Page (react-router). The page wasn't connected since it wasn't ready yet. Apparently after connecting the page (parent component which holds the list) everything works fine and i can see all 4 of my items (instead of seeing 3 without having the parent connected).

I wonder if this is intended...

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