Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Props not updating when redux state change in React Hooks

I am trying to implement Redux on a React Hooks project, but it doesnt seems to work good. Am I doing something wrong here?

reducer.js

const initialState = {
    educations: []
};

export default function home(state = initialState, action){
    switch(action.type){
        case GET_EDUCATIONS: {
            state.educations = action.payload;
            return state;
        }
        default:
            return state;
    }
}

action.js

import * as types from '../constans/home';

export const getEducations = () => {
    return dispatch => {
        const edus = [
            {value: 1, name: 'Bachelor'},
            {value: 2, name: "Master"}
        ]

        dispatch({
            type: types.GET_EDUCATIONS,
            payload: edus
        })
    }
}

component

import React, {useEffect} from 'react';
import {connect} from 'react-redux';
import {getEducations} from '../../redux/actions/home';

function Header({educations, getEducations}) { 
    useEffect(() => {
        getEducations(); //calling getEducations()
    }, [])

    useEffect(() => {
        console.log(educations) //console educations after every change
    })

    return (
        <div className="main-header">
        </div>
    )
}

const mapStateToProps = (state) => {
    return {
        educations: state.home.educations
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        getEducations: () => { dispatch(getEducations())}
    }
}

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

And the education property in Header function is always an empty array, as in initialState. While when I check on browser with Redux Devtools, it shows that the state contains those two object in array. enter image description here

So no matter if I change the redux state or not, the properties of the component are going to stay as initialState.

like image 794
Ertan Hasani Avatar asked Feb 04 '23 17:02

Ertan Hasani


1 Answers

In redux, you should avoid directly mutating the state of your reducer. Refrain from doing something like state.reducers = blah. In order for redux to know that you are trying to make an update to state, you need to return a completely new state object. Following these principles, your reducers will update correctly and your components will get the new data.

Reducer.js

const initialState = {
    educations: []
};

export default function home(state = initialState, action){
    switch(action.type){
        case GET_EDUCATIONS: {
            return {
               ...state,
               educations: action.payload
            };
        }
        default:
            return state;
    }
}

In the code above, we return a new state object. It will include everything from the existing state, hence ...state, and we just update the educations property with the action.payload.

like image 151
Chris Ngo Avatar answered Feb 19 '23 19:02

Chris Ngo