Это регистрирует предыдущее значение, так как оно было в области видимости, когда функция была определена, перед ее вызовом.
Если вы действительно хотите записать правильное значение, которое в конечном итоге будет (как setState
is asyn c) переведите его в состояние в том же месте, просто запишите item.name
.
В качестве альтернативы, если вы хотите регистрировать значение только после того, как оно уже находится в состоянии, вы должны использовать useEffect
, передавая ему значения, на которые вы хотите реагировать, как deps
:
// We want React to call this function every time `selectedAwayName` changes:
useEffect(() => {
console.log('Away Team name:', selectedAwayName);
}, [selectedAwayName]);
Здесь вы можете увидеть, что происходит и как useEffect
исправляет это:
const App = () => {
const [selectedHomeName, setSelectedHomeName] = React.useState('');
const [selectedAwayName, setSelectedAwayName] = React.useState('');
// When the component renders for the first time, this function is created,
// and the `selectedHomeName` value that will log when called is the one
// currently in scope, that is, an empty string.
// When the component re-renders, a new function is created again with the
// value currently in scope, which is the one we set previously. When changed
// again, it will log the previous value, not the new one:
const selectHomeTeamStat = ({ target }) => {
setSelectedHomeName(target.textContent);
console.log('PREVIOUS Home Team =', selectedHomeName);
};
const selectAwayTeamStat = ({ target }) => {
setSelectedAwayName(target.textContent);
console.log('PREVIOUS Away Team =', selectedAwayName);
};
// We are telling React to call this function every time `selectedHomeName` or
// `selectedAwayName` change:
React.useEffect(() => {
console.log(`CURRENT TEAMS = ${ selectedHomeName } / ${ selectedAwayName }`);
}, [selectedHomeName, selectedAwayName])
return (<React.Fragment>
<nav className="buttons">
<button onClick={ selectHomeTeamStat }>Home Team 1</button>
<button onClick={ selectHomeTeamStat }>Home Team 2</button>
<button onClick={ selectAwayTeamStat }>Away Team 1</button>
<button onClick={ selectAwayTeamStat }>Away Team 2</button>
</nav>
<div>{ selectedHomeName } / { selectedAwayName }</div>
</React.Fragment>);
}
ReactDOM.render(<App />, document.querySelector('#app'));
body,
button {
font-family: monospace;
}
body, p {
margin: 0;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
}
.buttons {
display: flex;
margin: 32px 0;
}
button {
margin: 0 4px;
padding: 8px;
border: 2px solid black;
background: transparent;
cursor: pointer;
border-radius: 2px;
}
.as-console-wrapper {
max-height: 45px !important;
}
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
С учетом этих изменений теперь вы можете использовать useCallback
, чтобы эти две функции не создавались повторно. при каждом повторном рендеринге, поскольку им больше не нужен доступ к selectedHomeName
или selectedAwayName
:
const selectHomeTeamStat = React.useCallback(({ target }) => {
setSelectedHomeName(target.textContent);
}, []);
const selectAwayTeamStat = React.useCallback(({ target }) => {
setSelectedAwayName(target.textContent);
}, []);