0

I discovered that my reducer was being called twice for each dispatch after noticing that some of my code's functionality was broken. Now I found out that it is due to the <StrictMode>. I would hate to remove this. If I turn on my debugger (StrictMode still there), I get this error

  Cannot update a component (`ForwardRef(TouchRipple)`) while rendering a different component 

As you can see, I build my provider according to the reducer-dispatch pattern

I'm posting the code, with very simple naming.

types

export type ValueState = {
    value: string | null;
};


export enum AcionType {
    SetValue,
}
export interface SetValue {
    type: AcionType.SetValue;
    value: string | null;
}

export type ValueActions = SetValue;

export type ValueDispatch = Dispatch<ValueActions>;

export type ValueContextState = {
    state: ValueState;
    dispatch: ValueDispatch;
};

reducer

export const valueReducer = (state: ValueState, action: ValueActions): ValueState => {
    console.log("reducer") // getting called two times!!;
    switch (action.type) {
        case AcionType.SetValue:
            return {
                ...state,
                value: test(action.value),
            };
        default:
            return state;
    }
};
const test = (value: string | null) => {
    debugger;
    return value;
};

Context

export const ValueContext = createContext<ValueContextState>({
    state: getDefaultState(),
    dispatch: () => {},
});

    export const ValueProvider = ({ children }: Props) => {
        const [state, dispatch] = useReducer<React.Reducer<ValueState, ValueActions>>(valueReducer, getDefaultState());
    
        const [contextValue, setContextValue] = useState<ValueContextState>({
            state,
            dispatch,
        });
    

        useEffect(() => {
            setContextValue((contextValue: ValueContextState) => ({
                ...contextValue,
                state,
            }));
        }, [state]);
    
        return <ValueContext.Provider value={contextValue}>{children}</ValueContext.Provider>;
    };
    
    function getDefaultState(): ValueState {
        return {
            value: null,
        };
    }
    
    type Props = {
        children: React.ReactNode;
    };

customHook

export const useValues = () => {
    const { state, dispatch } = useContext(ValueContext);

    const setValue = useCallback(
        (value: string | null) => {
         console.log("dispatch") // getting called once!
            dispatch({
                type: AcionType.SetValue,
                value: value,
            });
        },
        [dispatch],
    );

    return {
        value: state.value,
        setValue: setValue,
    };
};

Using Provider

<Routes>
            <Route
                index
                element={
                    <ValueProvider>
                        <Values />
                    </ValueProvider>
                }
            />
        </Routes>

making dispatch

 export const Value = () => {
        const { setValue } = useValues();
        return <InputComponent onChange={(e) => setValue(e.target.value)} />;
    };
maxfromgermany
  • 239
  • 4
  • 17
  • 1
    Could this be it: https://stackoverflow.com/questions/48846289/why-is-my-react-component-is-rendering-twice ? It is quite common reason for such problems. You can use the most upvoted answer to test it out. – axordahaxor Jul 19 '22 at 07:36
  • I cant believe it. I sat loosely 3 days at the measures. Should that be turned off? Is it good – maxfromgermany Jul 19 '22 at 07:40
  • Well, there is a debate whether it should be turned off or not. In my view it is fine to be kept on if you can be sure that the double render problem is caused by that 'extra caution measure'. Its intention is good but it can cause confusion. So, try taking it off to see if it fixes your problem. If it does, great. Then you know there is nothing else wrong with it. Double render only happens in dev environment, so when running it in production mode, this shouldn't happen anymore if it was because of this extra measure. So, take it off, see if it works and put it back on in my opinion. – axordahaxor Jul 19 '22 at 07:58
  • Could you please take a look here. https://stackoverflow.com/a/73004815/17682036 Do you know why the functional solution is not working? Hope it is not to random – maxfromgermany Jul 19 '22 at 08:01
  • @axordahaxor i completely reformulated my question – maxfromgermany Jul 19 '22 at 09:05
  • Would you mind building a code sandbox(https://codesandbox.io) that matches exactly your situation right now? So that it shows the error and has all the logging and everything in place to reproduce the problem? I'm sure me and other people would like to see it and tinker with it :) – axordahaxor Jul 19 '22 at 09:42
  • Also, this https://stackoverflow.com/questions/62336340/cannot-update-a-component-while-rendering-a-different-component-warning came up while searching for your error and it could help resolve it. Again two of the most common upvoted answers could help you in the problem. – axordahaxor Jul 19 '22 at 09:46
  • Many Thanks. Yes, I already know the post. He doesn't help me. I don't know if it's react 16. I only get the error with the debugger. I can try to show the logic there, but it will take some time – maxfromgermany Jul 19 '22 at 10:22
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/246571/discussion-between-maxfromgermany-and-axordahaxor). – maxfromgermany Jul 19 '22 at 10:22

0 Answers0