Estoy tratando de usar Context y Reducers a través de los ganchos de React, y tengo problemas con el orden de los ganchos que no es constante. Entendí que siempre que el orden de useHook(…) permaneciera igual, estaba bien invocar el estado devuelto/función de actualización/reductor en cualquier tipo de flujo de control. De lo contrario, estoy invocando los ganchos al principio de los componentes de función.
¿Es que estoy generando Days en un bucle? ¿O falta algo más?
Warning: React has detected a change in the order of Hooks called by Container. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/docs/hooks-rules.html Previous render Next render ------------------------------------------------------ 1. useContext useContext 2. undefined useRef ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ La versión completa de Container se encuentra a continuación. Un extracto de Day está a continuación, y tiene una referencia de useDrop de react-dnd .
export const Container: FunctionComponent<Props> = () => { let events = useContext(State.StateContext) //let events: Array<Event.Event> = [] <- with this, no warning const getDaysEvents = (day: Event.Time, events: Array<Event.Event>) => { return events.map(e => { const isTodays = e.startTime.hasSame(day, "day") return isTodays && Event.Event({ dayHeight, event: e }) }) } let days = [] for (let i = 0; i < 7; i++) { const day = DateTime.today().plus({ days: i }) days.push( <Day key={day.toISO()} height={dayHeight} date={day}> {getDaysEvents(day, events)} </Day> ) } return <div className="Container">{days}</div> } Un extracto de Day ( Event usa de manera similar un gancho useDrag , también llamado en el nivel superior como aquí).
const Day: FunctionComponent<DayProps> = ({ date, height, children }) => { const dispatch = useContext(State.DispatchContext) const [{ isOver, offset }, dropRef] = useDrop({ // …uses the dispatch function within… // … }) // … }Me encontré con este mismo mensaje de error en un componente que estaba escribiendo debido al uso de lógica de cortocircuito.
Esto resultó en un error:
const x = useSelector(state => state.foo); if (!x) { return ; } const y = useSelector(state => state.bar); Esto se debe a que cuando x es verdadero, la lista de ganchos tiene una longitud de 2, pero cuando x es falso, la lista tiene una longitud de 1.
Para resolver el error, tuve que usar todos los ganchos antes de las terminaciones anticipadas.
const x = useSelector(state => state.foo); const y = useSelector(state => state.bar); if (!x) { return ; }Escribiendo mi comentario como respuesta:
El problema es que está llamando a Event.Event() directamente, aunque es un componente de reacción. Eso hace que reaccione para tratar las llamadas de gancho dentro de la función como parte de Container , a pesar de que pretendía que fueran parte de Event.
La solución es usar JSX:
return isTodays && <Event.Event dayHeight={dayHeight} event={e} />
Por qué esto funciona es más claro cuando reemplaza el JSX con el código JS resultante:
return isTodays && React.createElement(Event.Event, { dayHeight, event: e })
Consulte https://reactjs.org/docs/react-api.html#createelement . Nunca desea llamar a los componentes de la función directamente, la forma en que reacciona es que siempre entrega una referencia al componente para reaccionar y deja que llame a la función en el momento correcto.
Por otro motivo en lugar de esta pregunta, cuando recibe este error
En realidad, sucede debido a cualquier mala práctica para las implementaciones de ganchos.
No llame a Hooks dentro de bucles , condiciones o funciones anidadas . En cambio, siempre use Hooks en el nivel superior de su función React
NOTA: implemente sus
useStateprimero en la parte superior de la función
No llamar Hooks desde funciones regulares de JavaScript
Si obtiene este error al probar el componente, tenga cuidado con el lugar donde configura sus ganchos personalizados (reemplace en la parte superior de la función)
use eslint para lint su código evite obtener errores de reglas de React Hooks
instalar paquete con npm o yarn
npm install eslint-plugin-react-hooks --save-dev