programing

useRedcer 및 useContext를 사용하여 사용자 정의 후크에서 작업을 디스패치하는 방법

prostudy 2022. 3. 28. 21:40
반응형

useRedcer 및 useContext를 사용하여 사용자 정의 후크에서 작업을 디스패치하는 방법

버튼 토글을 위해 샘플을 만들었다.

이 일은 에 의해 이루어진다.useContext(데이터 저장) 및useReducer(데이터를 처리한다.잘 되고 있어.

CodeSandBox 링크는 어떻게 작동하는지 입니다.

version 1버튼을 클릭할 때 바로 전송하는 것이다.

그리고 나서 나는 a를 만들었다.version 2토글링에 대한 거야 그냥 주문제작 후크에 넣어두기만 하면 돼 근데 어떻게 된 거야?

// context
export const initialState = { status: false }

export const AppContext = createContext({
  state: initialState,
  dispatch: React.dispatch
})

// reducer
const reducer = (state, action) => {
  switch (action.type) {
    case 'TOGGLE':
      return {
        ...state,
        status: action.payload
      }
    default:
      return state
  }
}

//custom hook
const useDispatch = () => {
  const {state, dispatch} = useContext(AppContext)
  return {
    toggle: dispatch({type: 'UPDATE', payload: !state.status})
    // I tried to do toggle: () => dispatch(...) as well
  }
}

// component to display and interact
const Panel = () => {
  const {state, dispatch} = useContext(AppContext) 
  // use custom hook
  const { toggle } = useDispatch()
  const handleChange1 = () => dispatch({type: 'TOGGLE', payload: !state.status})
  const handleChange2 = toggle // ERROR!!!
  // and I tried handleChange2 = () => toggle, or, handleChange2 = () => toggle(), or handleChange2 = toggle()
  return (
    <div>
      <p>{ state.status ? 'On' : 'Off' }</p>
      <button onClick={handleChange1}>change version 1</button>
      <button onClick={handleChange2}>change version 2</button>
    </div>
  )
}

// root 
export default function App() {
  const [state, dispatch] = useReducer(reducer, initialState)
  return (
    <AppContext.Provider value={{state, dispatch}}>
      <div className="App">
        <Panel />
      </div>
    </AppContext.Provider>
  );
}

무슨 일이 일어나고 있는지 잘 모르겠어. 하지만 파견된 주(州)에 문제가 있는 것 같아.

(페이로드가 하드코드 같은 걸 처리하고 있지 않으면 효과가 있어, 지금 당장 디스패치를 해야 한다.

누가 좀 도와 줄래?고마워!!!

토글이 기능이 되어야 하는 것은 맞지만 당신은 작업 유형 UPDATE를 발송하고 있고 환원기는 그 작업으로 아무 것도 하지 않는다.

Dennis는 당신이 컨텍스트를 제공하는 초기 가치에는 의미가 없다는 것이 옳고 제공자가 그 가치를 제공할 것이기 때문에 그것을 비워두는 편이 낫다.

상태가 변경될 때 앱이 렌더링되어 메모된 값이 사용되지 않기 때문에 데니스의 useMemo 제안은 당신의 예를 최적화하지 않을 것이다.

다음은 코드의 작업 예시 및 내가 변경한 코멘트:

const { createContext, useReducer, useContext } = React;

const initialState = { status: false };
//no point in setting initial context value
const AppContext = createContext();

const reducer = (state, action) => {
  switch (action.type) {
    case 'TOGGLE':
      return {
        ...state,
        status: action.payload,
      };
    default:
      return state;
  }
};

const useDispatch = () => {
  const { state, dispatch } = useContext(AppContext);
  return {
    //you were correct here, toggle
    //  has to be a function
    toggle: () =>
      dispatch({
        //you dispatch UPDATE but reducer
        //  is not doing anything with that
        type: 'TOGGLE',
        payload: !state.status,
      }),
  };
};

const Panel = () => {
  const { state, dispatch } = useContext(AppContext);
  const { toggle } = useDispatch();
  const handleChange1 = () =>
    dispatch({ type: 'TOGGLE', payload: !state.status });
  const handleChange2 = toggle; // ERROR!!!
  return (
    <div>
      <p>{state.status ? 'On' : 'Off'}</p>
      <button onClick={handleChange1}>
        change version 1
      </button>
      <button onClick={handleChange2}>
        change version 2
      </button>
    </div>
  );
};

function App() {
  const [state, dispatch] = useReducer(
    reducer,
    initialState
  );
  return (
    <AppContext.Provider value={{ state, dispatch }}>
      <div className="App">
        <Panel />
      </div>
    </AppContext.Provider>
  );
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>


<div id="root"></div>

글쎄, 그런 건 없어.React.dispatch그것의 가치는undefined

export const AppContext = createContext({
  state: initialState,
  // useless
  // dispatch: undefined
  dispatch: React.dispatch
});

// dispatch function won't trigger anything.
const {state, dispatch} = useContext(AppContext);

버전 1은 실제로 컨텍스트를 사용하는 방법이지만, 일반적으로 새로운 개체를 할당할 때마다 추가 메모화 단계(사용 사례에 설명됨)를 추가하고자 할 것이다.{state,dispatch}항상 렌더링을 일으킬 수 있지만state같은 것일 수도 있다.

이러한 메모화 사용 사례 예를 참조하십시오.

블랙-스모크-6lz6k 편집

내 요점이 명확하지 않으면 HMR 코멘트를 참조하십시오.

전략적 활용Memo를 사용해야 하며, 많은 구성요소가 컨텍스트에 액세스하는 경우 컨텍스트 변경 이외의 이유로 프로바이더와의 컴포넌트를 재렌더할 때 메모를 하는 것이 좋다.

참조URL: https://stackoverflow.com/questions/62620281/how-to-dispatch-action-in-custom-hooks-by-usereducer-and-usecontext

반응형