我正在尝试通过 React 的挂钩使用 Context
和 Reducers
,并遇到挂钩顺序不恒定的问题。我的理解是,只要 useHook(…)
的顺序保持不变,就可以在任何类型的控制流中调用返回的状态/更新函数/reducer。否则,我将在 FunctionComponents 的最开始调用挂钩。
是我在循环中生成 Days
吗?还是缺少其他东西?
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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Container
的完整版本如下。下面是 Day
的摘录,并有来自 react-dnd
的 useDrop
的参考。
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>
}
摘录自 Day
( Event
同样使用 useDrag
挂钩,也像此处一样在顶层调用)。
const Day: FunctionComponent<DayProps> = ({ date, height, children }) => {
const dispatch = useContext(State.DispatchContext)
const [{ isOver, offset }, dropRef] = useDrop({
// …uses the dispatch function within…
// …
})
// …
}
原文由 Isaac 发布,翻译遵循 CC BY-SA 4.0 许可协议
写下我的评论作为答案:
问题是您正在直接调用
Event.Event()
,即使它是一个反应组件。这导致 React 将函数内的挂钩调用视为Container
的一部分,即使您想让它们成为 Event 的一部分。解决方案是使用 JSX:
return isTodays && <Event.Event dayHeight={dayHeight} event={e} />
当您将 JSX 替换为生成的 JS 代码时,为什么这会更清楚:
return isTodays && React.createElement(Event.Event, { dayHeight, event: e })
请参阅 https://reactjs.org/docs/react-api.html#createelement 。你永远不想直接调用函数组件,react 的工作原理是你总是传递一个引用组件来 react 并让它在正确的时间调用函数。