React Hook useEffect has a missing dependency: 'dispatch'

前端 未结 2 1121
既然无缘
既然无缘 2021-02-07 05:27

This is my first time working with react js , im trying to remove the alert when leaving this view cause i don\'t want to show it on the other view but in case that there is no

2条回答
  •  面向向阳花
    2021-02-07 06:27

    I think you can solve the problem at the root but that means changing useCombinedReducers, I forked the repo and created a pull request because I don't think useCombinedReducers should return a new reference for dispatch every time you call it.

    function memoize(fn) {
      let lastResult,
        //initial last arguments is not going to be the same
        //  as anything you will pass to the function the first time
        lastArguments = [{}];
      return (...currentArgs) => {
        //returning memoized function
        //check if currently passed arguments are the same as
        //  arguments passed last time
        const sameArgs =
          currentArgs.length === lastArguments.length &&
          lastArguments.reduce(
            (result, lastArg, index) =>
              result && Object.is(lastArg, currentArgs[index]),
            true,
          );
        if (sameArgs) {
          //current arguments are same as last so just
          //  return the last result and don't execute function
          return lastResult;
        }
        //current arguments are not the same as last time
        //  or function called for the first time, execute the
        //  function and set last result
        lastResult = fn.apply(null, currentArgs);
        //set last args to current args
        lastArguments = currentArgs;
        //return result
        return lastResult;
      };
    }
    
    const createDispatch = memoize((...dispatchers) => action =>
      dispatchers.forEach(fn => fn(action)),
    );
    const createState = memoize(combinedReducers =>
      Object.keys(combinedReducers).reduce(
        (acc, key) => ({ ...acc, [key]: combinedReducers[key][0] }),
        {},
      ),
    );
    const useCombinedReducers = combinedReducers => {
      // Global State
      const state = createState(combinedReducers);
    
      const dispatchers = Object.values(combinedReducers).map(
        ([, dispatch]) => dispatch,
      );
    
      // Global Dispatch Function
      const dispatch = createDispatch(...dispatchers);
    
      return [state, dispatch];
    };
    
    export default useCombinedReducers;
    

    Here is a working example:

    const reduceA = (state, { type }) =>
      type === 'a' ? { count: state.count + 1 } : state;
    const reduceC = (state, { type }) =>
      type === 'c' ? { count: state.count + 1 } : state;
    const state = { count: 1 };
    function App() {
      const [a, b] = React.useReducer(reduceA, state);
      const [c, d] = React.useReducer(reduceC, state);
      //memoize what is passed to useCombineReducers
      const obj = React.useMemo(
        () => ({ a: [a, b], c: [c, d] }),
        [a, b, c, d]
      );
      //does not do anything with reduced state
      const [, reRender] = React.useState();
      const [s, dispatch] = useCombinedReducers(obj);
      const rendered = React.useRef(0);
      const [sc, setSc] = React.useState(0);
      const [dc, setDc] = React.useState(0);
      rendered.current++;//display how many times this is rendered
      React.useEffect(() => {//how many times state changed
        setSc(x => x + 1);
      }, [s]);
      React.useEffect(() => {//how many times dispatch changed
        setDc(x => x + 1);
      }, [dispatch]);
      return (
        
    rendered {rendered.current} times
    state changed {sc} times
    dispatch changed {dc} times
    {JSON.stringify(s, undefined, 2)}
    ); } function memoize(fn) { let lastResult, //initial last arguments is not going to be the same // as anything you will pass to the function the first time lastArguments = [{}]; return (...currentArgs) => { //returning memoized function //check if currently passed arguments are the same as // arguments passed last time const sameArgs = currentArgs.length === lastArguments.length && lastArguments.reduce( (result, lastArg, index) => result && Object.is(lastArg, currentArgs[index]), true ); if (sameArgs) { //current arguments are same as last so just // return the last result and don't execute function return lastResult; } //current arguments are not the same as last time // or function called for the first time, execute the // function and set last result lastResult = fn.apply(null, currentArgs); //set last args to current args lastArguments = currentArgs; //return result return lastResult; }; } const createDispatch = memoize((...dispatchers) => action => dispatchers.forEach(fn => fn(action)) ); const createState = memoize(combinedReducers => Object.keys(combinedReducers).reduce( (acc, key) => ({ ...acc, [key]: combinedReducers[key][0], }), {} ) ); const useCombinedReducers = combinedReducers => { // Global State const state = createState(combinedReducers); const dispatchers = Object.values(combinedReducers).map( ([, dispatch]) => dispatch ); // Global Dispatch Function const dispatch = createDispatch(...dispatchers); return [state, dispatch]; }; ReactDOM.render(, document.getElementById('root'));
    
    
    

提交回复
热议问题