Нажмите здесь, чтобы прочитать статью на японском языке:https://zenn.dev/takuyakikuchi/articles/2c4071a58bd4d7
Содержание
- console.log() для проверки времени рендеринга
- 1. Обновление состояния в родительском и дочернем компоненте и повторный рендеринг
- Что нужно подтвердить
- Код
- Результаты консоли
- Подтверждено
- Демонстрация
- 2. useState initialState против ленивого начального состояния
- Что нужно подтвердить
- Код
- Результат консоли
- Подтверждено
- Демонстрация
- 3. Время выполнения useEffect
- Вещи, которые необходимо подтвердить
- Код
- Результат работы консоли
- Подтверждено
- Демонстрация
- Резюме
console.log()
для проверки времени рендеринга
⚠️ Для упрощения протоколирования результатов, «Строгий режим» намеренно отключен, чтобы жизненный цикл никогда не вызывался дважды.
Строгий режим — React
1. Обновление состояния в родительском и дочернем компоненте и повторный рендеринг
Что нужно подтвердить
- Проверьте повторный рендеринг при изменении состояния в родительском и дочернем компонентах.
Код
- Родительский компонент:
App
- Дочерний компонент:
count
.- Имеет состояние
count
.
- Имеет состояние
const ChildA = ({ state }) => {
const [count, setCount] = React.useState(0);
+ console.log(`rendering in child A component: count has ${count}`);
return (
...
<button onClick={() => setCount(count + 1)}>Child A: Count-up</button>
...
);
};
const ChildB = () => {
console.log("rendering in child B component");
return <div>Child B doesn't have props passed from the parent</div>;
};
export default function App() {
const [state, setState] = React.useState(false);
console.log("rendering in parent component");
return (
<div className="App">
...
<button onClick={() => setState(!state)}>Update the parent state</button>
...
<ChildA state={state} />
...
<ChildB />
</div>
);
}
Результаты консоли
<!-- 1. Initial rendering -->
rendering in parent component
rendering in child A component: count has 0
rendering in child B component
<!-- 2. Update the parent state -->
rendering in parent component
rendering in child A component: count has 0
rendering in child B component
<!-- 3. Update the child A state -->
rendering in child A component: count has 1
<!-- 4. Update the parent state -->
rendering in parent component
rendering in child A component: count has 1
rendering in child B component
Подтверждено
- При изменении состояния родительского компонента перерисовка происходит как в родительском, так и в дочерних компонентах, независимо от того, передаются реквизиты или нет. (См. № 2)
- Когда состояние изменяется в дочернем компоненте, перерисовка происходит только в этом компоненте. (См. № 3)
- Когда родительский компонент перерендеривается, а дочерний компонент перерендеривается, состояние дочернего компонента поддерживается в актуальном состоянии. (См. № 4)
Демонстрация
2. useState initialState против ленивого начального состояния
Что нужно подтвердить
- Подтвердите, что ленивое начальное состояние вызывается только при начальном рендеринге.
- С другой стороны, подтвердите, что
initialState
вызывается при каждом повторном рендеринге.
React: useState
Код
- Родительский компонент:
App
- Дочерний компонент:
Child
.
const someExpensiveCalculation = (number, type) => {
console.log(`in the ${type} initial state`);
return number * 10;
};
const Child = ({ number }) => {
const [childStateA, setChildStateA] = React.useState(() => {
return someExpensiveCalculation(number, "lazy");
});
const [childStateB, setChildStateB] = React.useState(
someExpensiveCalculation(number, "default")
);
console.log(
`rendering in child component: A: ${childStateA}, B: ${childStateB}`
);
return (
<>
<p>{`The childStateA is ${childStateA}`}</p>
<button onClick={() => setChildStateA(childStateA + 1)}>
Child A: Count-up
</button>
<p>{`The childStateB is ${childStateB}`}</p>
<button onClick={() => setChildStateB(childStateB + 1)}>
Child B: Count-up
</button>
</>
);
};
export default function App() {
const [state, setState] = React.useState(false);
return (
<div className="App">
<button onClick={() => setState(!state)}>Update the parent state</button>
<Child number={10} />
</div>
);
}
Результат консоли
<!-- 1. Initial rendering -->
in the lazy initial state
in the default initial state
rendering in child component: A: 100, B: 100
<!-- 2. Parent state update -->
in the default initial state
rendering in child component: A: 100, B: 100
<!-- 3. Child state A update -->
in the default initial state
rendering in child component: A: 101, B: 100
<!-- 3. Child state B update -->
in the default initial state
rendering in child component: A: 101, B: 101
<!-- 4. Parent state update -->
in the default initial state
rendering in child component: A: 101, B: 101
Подтверждено
- При ленивом начальном состоянии, someExpensiveCalculation()` вызывается только при начальном рендеринге, и игнорируется при повторном рендеринге.
- С другой стороны, когда значение передается просто как
initialState
, someExpensiveCalculation()` вызывается каждый раз при повторном рендеринге.
Демонстрация
3. Время выполнения useEffect
Вещи, которые необходимо подтвердить
- Убедитесь, что функция, переданная в
useEffect
, запускается после того, как результат рендеринга отражается на экране.
React: useEffect
Код
- В
useEffect
, гдеstate
является зависимым значением, обновите состояниеmessage
после получения данных.
const dataFetchMock = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("setMessage executed in useEffect");
}, 1500);
});
export default function App() {
const [message, setMessage] = React.useState();
const [state, setState] = React.useState(false);
React.useEffect(() => {
console.log(`in useEffect. state: ${state}`);
dataFetchMock.then((value) => {
setMessage(value);
});
}, [state]);
console.log(`rendering: just before return jsx. message: ${message}`);
return (
<div className="App">
<button onClick={() => setState(!state)}>Update the parent state</button>
<p>{message === undefined ? "undefined" : message}</p>
</div>
);
}
Результат работы консоли
<!-- 1. Initial rendering -->
rendering: just before return jsx. message: undefined
in useEffect. state: false
rendering: just before return jsx. message: setMessage executed in useEffect
<!-- 2. State(dependency of the useEffect) updated -->
rendering: just before return jsx. message: setMessage executed in useEffect
in useEffect. state: true
rendering: just before return jsx. message: setMessage executed in useEffect
Подтверждено
- * UseEffect работает после рендеринга. *
- Первоначальный рендеринг (см. №1), сначала рендеринг =>
useEffect
=> изменение состоянияmessage
вuseEffect
вызвало повторный рендеринг. - При обновлении состояния, содержащегося в массиве зависимостей
useEffect
(см. №2), рендеринг путем обновления состояния =>useEffect
=> повторный рендеринг путем изменения состоянияmessage
вuseEffect
.
- Первоначальный рендеринг (см. №1), сначала рендеринг =>
Демонстрация
Резюме
React можно использовать со смутным пониманием.
Однако я подумал, что было бы полезно самостоятельно проверить время повторного рендеринга и т.д.