Код ниже отобразит <h1> и два <button>.
В моем ожидании, changeString1<button> изменит letString на 1 и, наконец, изменит <h1> текст на 1, а changeString2<button>
<h1> текст на 3если я сначала нажму changeString2<h1> текст на 1если я сначала нажму changeString1Но по факту
changeString1однажды, затем нажму changeString2, <h1> текст будет 3 ! Но почему?changeString1дважды, затем нажму changeString2, <h1> текст будет 1 ! Но почему?Кажется, что оба факта противоречат друг другу...
Вы можете проверить это с помощью https://codesandbox.io/s/wy4l1y4o8
import React, { useState } from "react";
import ReactDOM from "react-dom";
function App() {
let letString = "3";
const [statString, setStatString] = useState("2");
function changeString1() {
letString = "1";
setStatString(letString);
}
function changeString2() {
console.info(letString);
setStatString(letString);
}
return (
<div>
<h1>{statString}</h1>
<button onClick = {changeString1}>changeString1</button>
<button onClick = {changeString2}>changeString2</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Когда вы нажимаете на изменитьСтрока2, значение локальной переменной letString равно 3.
Если вы хотите сохранить значение letString между циклами рендеринга, вы должны использовать использование состояния или даже использовать глобальную переменную области видимости (не рекомендуется).
но почему на самом деле 2, я нажимаю на changeString2 результаты, чтобы текст <h1> был 1?
Если вы поместите console.info('rendering', letString) непосредственно перед возвратом функции, вы увидите, что значение letString всегда равно '3' при рендеринге. Неважно, что вы меняете его внутри локальной функции changeString1, когда компонент собирается отрендериться, letString снова инициализируется значением 3.
Вы должны отслеживать нажатие на changeString1 в отдельной переменной:
const {useState} = React
function App() {
const [statString, setStatString] = useState("2");
const [clicked, setClicked] = useState(false)
function changeString1() {
setClicked(true)
setStatString("1");
}
function changeString2() {
setStatString(clicked ? "1" : "3");
}
return (
<div>
<h1>{statString}</h1>
<button onClick = {changeString1}>changeString1</button>
<button onClick = {changeString2}>changeString2</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);<script crossorigin src = "https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src = "https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id = "root" />Причина, по которой ваш код не работал должным образом, заключается в том, что каждый вызов App создает новый экземпляр переменной letState, которая связана с функцией changeString2, когда она равна определенный.
React оптимизирует вызовы, которые не изменяют состояние, избегая ненужного повторного рендеринга. Поэтому, когда вы нажимаете второй раз, вы не вызываете замены функций обратного вызова. Поэтому, когда вы нажимаете на changeState2, это та же функция, что и в «предыдущем» рендере.
Пожалуйста, посмотрите на поток, который имеет место: -
1st click on changeString1
state changes
component re renders
letString gets re-initialized to 3 because of let letString = "3"
value of letString = 3;
value of statString = 1 (state);
2nd click on changeString1
value of letString gets set to 1 in the function call;
But value of statString(state) is already 1 so no state changes and component never re-renders and letString is not re-initialized
After 2nd click values are:-
letString = 1;
statString = 1(state);
Now, when you click on changeString2 value of letString is 1 and statString is also 1 so state doesn't changes and nothing happens and you just see 1.
Это имеет смысл. Я попытался добавить третью кнопку с именем changeString3, которая вызывает выполнение функции setStatString("4");. После того, как я дважды щелкну changeString1 и щелкну один раз changeString3, щелкните один раз changeString2, наконец, результат <h1> text будет 3 снова. Таким образом, ключевым моментом является то, что если компонент не нуждается в повторном рендеринге, его локальные переменные не будут повторно инициализированы?
Да, ты понял. Когда компонент не визуализируется повторно, letString не запускается повторно и остается без изменений. Но не в случае с государством. Состояние инициализируется только один раз при монтировании компонента, а не при дальнейшем повторном рендеринге.
Я думаю, вы нашли артефакт. Совет типа «не использовать локальную переменную» решит ваш случай, но не отвечает на вопрос, почему он остается «1» после двух щелчков мыши. Теоретически он не должен зависать на "1".