В React Hooks мы можем вызывать setState()
перехватчика состояния React непосредственно внутри функционального компонента. Это описано в официальных документах React здесь .
В соответствии с документами:
[Y] вы можете обновить состояние прямо во время рендеринга. React перезапустит компонент с обновленным состоянием сразу после выхода из первого рендера.
Что мне неясно, так это то, означает ли первый рендеринг первый рендеринг всего дерева компонентов , или только первый рендер компонента, который называется setState()
? Кроме того, что происходит с эффектами, которые запланированы во время этого рендера? Они выполняются или отбрасываются?
Это различие важно для моего варианта использования, потому что я вызываю setState()
внутри функции рендеринга, чтобы поддерживать состояние в синхронизации c с подпорками, как описано Даном Абрамовым здесь . В моем случае использования состояние, которое синхронизируется с опорой и исходной опорой, передается ребенку. Я хочу иметь возможность полагаться на тот факт, что реквизиты и состояние находятся в syn c у дочерних элементов, что не будет иметь место, если родительский рендеринг перерисовывается только после рендеринга всего дерева компонентов.
МОИ ИСПЫТАНИЯ
Я проверил это, и похоже, что setState()
выполняет повторную визуализацию компонента непосредственно перед визуализацией любого дочернего компонента и любые эффекты, запланированные во время первоначальный рендер отбрасывается. Это поведение, которое я хочу. Однако я не знаю, что это за спецификация. Могу ли я полагаться на это поведение во всех случаях?
КОД
Вот код, иллюстрирующий это конкретно:
function Foo({x}) {
const [xPlus1, setXPlus1] = React.useState(x + 1)
if (xPlus1 !== x + 1) setXPlus1(x + 1)
useEffect(()=>{
// Am I guaranteed that this will never throw?
if (xPlus1 !== x + 1) throw new Error()
})
return <Bar x={x} xPlus1={xPlus1} />
}
function Bar({x, xPlus1}) {
// Am I guaranteed that this will never throw?
if (xPlus1 !== x + 1) throw new Error()
return <p> {x} + 1 = {xPlus1} </p>
}