В React Hooks, при вызове setState непосредственно во время рендеринга, гарантируется ли повторный рендеринг перед рендерингом дочерних элементов? - PullRequest
1 голос
/ 04 марта 2020

В 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>
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...