Стиль кода useState
С помощью useState происходит рендринг чтобы поменялось значение на странице, везде вижу, что используют только тип данных const и меняют значение вот такsetCount(count+1); Можно ли использовать, let при создание useState и менять так count+=1;setCount(count+1); ? или так не рекомендовано?
let [count,setCount]=useState(0)
const [count,setCount]=useState(0)
Ответы (2 шт):
Немного сумбурно получилось...
Можно использовать конструкцию
let [a, setAa] = React.useState(0);
a++;
Нам это никто не запрещает, особенно, что мы можем это сделать. Только это не приведет к изменению самого состояния.
Да, можно сделать так:
let [a, setAa] = React.useState(0);
a++;
setA(a);
НО! Это не рекомендовано и даже не правильно, однако, да, можно так сделать :)
const используют для того, что бы уберечь себя от случайного изменения данных.
Однако есть Объекты. React это все тот же javaScript и useState возвращает не склонированный объект, а ссылку на него, поэтому можно "неумышленно" изменить состоние компонента.
const [obj, setObj] = React.useState({ a: 5 });
obj.c = 'new';
Теперь и в компоненте obj и в состоянии одни и те же данные, однако, такое изменение не вызовет ререндер компонента, так как передается ссылка на тот же объект и при сравнении, старые данные и новые будут равны. Такого поведения стоит избегать.
const [obj, setObj] = React.useState({ a: 5 });
obj.c = 'new';
setObj(obj); // не вызовет повтоный рендеринг
Для возможности повторного рендера при работе с объектами, лучше использовать spread оператор
const [obj, setObj] = React.useState({ a: 5 });
obj.c = 'new';
setObj({ ...obj }); // вызовет повтоный рендеринг
Ниже полный код с приведенными выше примерами:
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
const ObjChange = () => {
const [obj, setObj] = React.useState({ a: 5 });
const [arr, setArr] = React.useState([1, 2]);
const changeObj = () => {
obj.b = obj.b ? ++obj.b : 1;
setObj(obj);
arr.push(3);
setArr(arr);
};
const changeObjUpd = () => {
obj.b = obj.b ? ++obj.b : 1;
setObj({ ...obj });
arr.push(3);
setArr([...arr]);
};
return (
<div>
Текущее состояние объекта: {obj.a} {obj.b}
<br />
Текущее состояние массива: {arr.map((i) => i)}
<br />
<button onClick={() => changeObj()}>Поменять данные</button>
<button onClick={() => changeObjUpd()}>Поменять данные и обновить</button>
</div>
);
};
function App() {
let [a, Sa] = React.useState(0);
console.log("Begin", a);
a++;
a++;
a++;
a++;
console.log("End", a);
return (
<div className="App">
<h1>
a: {a}
<button
onClick={() =>
Sa((e) => {
console.log("Current", e);
return e + 10;
})
}
>
Прибавить 10
</button>
</h1>
<hr />
<ObjChange />
</div>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js"></script>
<div id='root'></div>
В дополнение к предыдущему ответу.
setState(count + 1) - так не рекомендуется делать.
setState((currentCount) => currentCount + 1) используйте коллбэк, чтобы избежать нечто похожего на гонку данных, в том случае, если событие, вызывающее setState(), будет слишком быстро срабатывать (к примеру, очень быстро кликать на кнопку, которая меняет счетчик).