es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Forma correcta de actualizar un estado dentro de useReducer (React.js)

Tengo dos entradas ‘select’ (html) que funcionan juntas para mostrar información, este es el estado:

const [foodValues, setFoodValues] = useState({ type: 'Todo', category: 'Todo' })

Todo funciona muy bien, estoy usando un handleChange() clásico en ambas entradas:

const handleChange = e => {
    const value = e.target.value 
    const name = e.target.name
    dispatch({type: ACTIONS.CHANGE, payload: {e: value, name: name}})
}

Como puedes ver, llamo al dispatch para usar el useReducer:

const OperationsReducer = (foodReducer, action) => {
  const { foodValues, setFoodValues } = useContext(AllContext)

  switch (action.type) {
    case ACTIONS.CHANGE:
      setFoodValues({
        ...foodValues,
        [action.payload.name]: action.payload.e
      })
    break;
  }
}

¡Y funciona muy bien! Pero estoy obteniendo esta advertencia en la consola:

Advertencia: No llames Hooks dentro de useEffect(…), useMemo(…), u otros Hooks integrados. Solo puedes llamar Hooks en el nivel superior de tu función React. Para obtener más información, consulte

Entonces, mi pregunta es: ¿hay alguna forma de usar este useReducer sin esa advertencia? Sé que podría simplemente usar setFoodValues fuera de él, pero estoy curioso (realmente me gusta usar useReducer…). Ya he leído la documentación de React sobre este tema, pero vi a algunas personas haciendo cosas realmente raras (y geniales) para evitar esto.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Sí, hay una forma de usar el gancho useReducer sin activar esa advertencia. La advertencia ocurre porque estás llamando al gancho useContext dentro de la función reductora, que es un gancho integrado y solo debe usarse en el nivel superior de tu componente.

    Para solucionar esto, puedes pasar las variables foodValues y setFoodValues como argumentos a tu función reductora en lugar de usar el gancho useContext dentro de ella. Aquí tienes un ejemplo:

    const OperationsReducer = (state, action, setFoodValues) => {
      switch (action.type) {
        case ACTIONS.CHANGE:
          return {
            ...state,
            [action.payload.name]: action.payload.e
          };
        default:
          return state;
      }
    };
    
    // en tu componente
    const [foodValues, dispatch] = useReducer(
      state => state,
      { type: 'Everything', category: 'Everything' }
    );
    
    const handleChange = (e) => {
      const value = e.target.value;
      const name = e.target.name;
    
      dispatch({ type: ACTIONS.CHANGE, payload: { e: value, name: name } });
    };
    
    // ...
    
    const handleSelectChange = (e) => {
      const name = e.target.name;
      const value = e.target.value;
      OperationsReducer(foodValues, { type: ACTIONS.CHANGE, payload: { e: value, name: name } }, setFoodValues);
    };
    

    En este ejemplo, pasamos setFoodValues como un argumento a la función reductora y la llamamos con el estado actualizado dentro de la función. Luego, en tu función handleSelectChange(), puedes llamar manualmente a la función reductora y pasar la función setFoodValues. De esta manera, aún puedes usar useReducer sin activar la advertencia sobre llamar ganchos dentro de un gancho.

Comments are closed.