Если у меня много useState
и одним нажатием кнопки я вызываю несколько setHook
, рендерится ли он несколько раз или только один раз?
например
export default function setMultipleHooks() {
const [hook1, setHook1] = useState(false)
const [hook2, setHook2] = useState(false)
const [hook3, setHook3] = useState(false)
const [hook4, setHook4] = useState(false)
const setHooks = () => {
setHook1(true)
setHook2(true)
setHook3(true)
setHook4(true)
}
return (
<button onClick = {setHooks} >Hey</button>
)
}
Когда я нажимаю кнопку, сколько раз она отображается? 1 или 4 раза?
Обычно, чтобы проверить, сколько раз рендерится компонент, я просто добавляю console.info
в метод render
, но с функциональными компонентами я не знаю, как это проверить.
Если он рендерится 4 раза, было бы лучше использовать только один useState
(передача объекта), если 4 хука всегда связаны?
React может пакетировать несколько вызовов setState и отображать их все сразу. И в вашем случае это происходит, потому что вы находитесь внутри обработчика событий (onClick).
Он рендерится только один раз (начальный рендер не включен), как вы можете видеть из фрагмента ниже.
Проблема Github с пакетными вызовами setState() React
Тем не менее, вы можете использовать объект с 4 свойствами вместо 4 переменных состояния хуков. Но вам нужно быть осторожным при обновлении состояния, потому что setState() хука не объединяет ваше последнее состояние автоматически с вашим новым свойством состояния. Он полностью заменяет состояние новым объектом, который вы передаете.
React Docs — Использование хука состояния
Итак, вам нужно сделать что-то вроде этого:
function YourComponent() {
const INITIAL_STATE = {a: false, b: false, c: false, d: false};
const [state,setState] = useState(INITIAL_STATE);
function handleClick() {
setState((prevState) => {
return({
...prevState,
b: true
});
});
}
}
const { useState, useRef, useEffect } = React;
function App() {
const renderTimes = useRef(0);
const [hook1, setHook1] = useState(false);
const [hook2, setHook2] = useState(false);
const [hook3, setHook3] = useState(false);
const [hook4, setHook4] = useState(false);
const setHooks = () => {
setHook1(true);
setHook2(true);
setHook3(true);
setHook4(true);
}
useEffect( () => {
renderTimes.current+=1;
});
return (
<div>
<div>I rendered {renderTimes.current} time(s).</div>
<div>NOTE: The initial render is not included.</div>
<div>State hook1 is equal to: {hook1.toString()}</div>
<div>State hook2 is equal to: {hook2.toString()}</div>
<div>State hook3 is equal to: {hook3.toString()}</div>
<div>State hook4 is equal to: {hook4.toString()}</div>
<button onClick = {setHooks}>Click</button>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id = "root"></div>
Я просто добавил useRef()
для хранения счетчика рендеринга и useEffect()
для увеличения счетчика рендеринга, так как он запускается после каждого рендера.
Normally to check how many times the component is rendering, I just put a console.info in the render method, but with functional components, I'm not sure how to test this.
Просто поместите console.info внутрь функции (сама функция является render
методом).
Он будет отображаться только один раз, потому что существует небольшой интервал времени, в течение которого, если произойдет несколько вызовов установщика useState, их обновления будут пакетными.
If it renders 4 times, it would be better to use only one useState (passing an object) if the 4 hooks are always related?
Если у вас сложное состояние, вам действительно следует подумать useReducer
.
Более:
Возможный дубликат stackoverflow.com/questions/53048495/…