0
votes

Why does the component dispatching an action for updating react-redux state re-renders after store state changes? Shouldn't the re-render occur only when props or component state changes?

const BoxContainer=memo(({props})=>{


    const dispatch = useDispatch();

    //Setting action with dispatch with useCallBack hook for safe side

    const callAction =useCallback(
        (payload) => {
            dispatch(payload)
        },
        [],
    );
    const structure = useSelector(state => ({...state.FormState}));
    var form = generateForm(structure,callAction);

    return(   
        <React.Fragment>
                {form}
        </React.Fragment>

    );
});

Reducer code is given below

export const FormState = (state = FormStructureState ,action) =>
{   
    switch(action.type){
        case 'UPDATE':
            return {
                ...state,
                Structure:action.Payload
            }
        case 'MOVEITEM':
              var sourceRow = action.sourceRow;
              var sourceCol = action.sourceCol;
              var destRow = action.destRow;
              var destCol = action.destCol;
              var destinationContent = state.Structure.row[destRow][destCol].content;
              state.Structure.row[destRow][destCol].content = state.Structure.row[sourceRow][sourceCol].content;
              state.Structure.row[sourceRow][sourceCol].content = destinationContent;
              return {...state}
        case 'SETTEMPLATE':
              var sourceRow = action.sourceRow;
              var sourceCol = action.sourceCol;
              state.Structure.row[sourceRow][sourceCol].content.template = action.template;
        default:
            return {...state}

    }


}
1

1 Answers

3
votes

Because your selector is unconditionally returning a new object every time:

useSelector(state => ({...state.FormState}));

useSelector will force a re-render if the return value is a new reference. Don't do that.

Also, as a side note, your current reducer logic has a number of issues. In particular, these lines are mutating the existing state:

state.Structure.row[destRow][destCol].content = state.Structure.row[sourceRow][sourceCol].content;

Don't do that.

There's also some stylistic issues:

  • Avoid using var
  • Use destructuring syntax to pull out variables, like const {sourceRow, sourceCol} = action

I'd strongly encourage you to switch to using our official Redux Toolkit package, which will catch accidental mutations by default, and also allow you to write simpler reducer logic.