javascript - React - SetState 处理程序方法
问题描述
我有一个具有以下情况的组件:
这是我在两个选择组件中选择两个团队(主队、客队)时的两种方法
const selectHomeTeamStat = evt => {
const { value } = evt.target;
setSelectedHomeOption(value);
getStats(leagueId, value, 'home');
};
const selectAwayTeamStat = evt => {
const { value } = evt.target;
setSelectedAwayOption(value);
getStats(leagueId, value, 'away');
};
如您所见,我可以将此字符串参数“ Home ”和“ Away ”传递给getStats
请求,以便区分并创建两种不同的状态
之后我意识到,我实际上需要将团队的状态名称作为参数传递给请求,而不是字符串“ Home ”和“ Away ”getStats
所以这改为
const [selectedHomeName, setSelectedHomeName] = useState("");
const [selectedAwayName, setSelectedAwayName] = useState("");
const selectHomeTeamStat = evt => {
const { value } = evt.target;
const item = items.find(item => item.team_id == value);
setSelectedHomeOption(value);
setSelectedHomeName(item.name);
console.log('Home Team Name:', selectedHomeName);
getStats(leagueId, value, selectedHomeName);
};
const selectAwayTeamStat = evt => {
const { value } = evt.target;
const item = items.find(item => item.team_id == value);
setSelectedAwayOption(value);
setSelectedAwayName(item.name);
console.log('Away Team name:', selectedAwayName);
getStats(leagueId, value, selectedAwayName);
};
item.name
正确返回所选团队的名称,因此我也希望看到selectedHomeName
并selectedAwayName
声明,但在我的中console.log
我看不到它
console.log('Home Team Name:', selectedHomeName); => Team Name:
console.log('Away Team Name:', selectedAwayName); => Away Name:
所以问题是,我做错了什么?我如何将这些状态传递到getStats
事件处理程序内部以区分?
解决方案
这是在调用它之前记录上一个值,因为这是定义函数时范围内的值。
如果您真的想记录最终将要(如setState
异步)使其进入同一位置的状态的正确值,只需 log 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);
}, []);
推荐阅读
- javascript - RxJs mergeScan 运算符不能通过 Promise 中的流 flatMap 累积?
- r - 如何从变量中传递分组中的列名
- amazon-web-services - 如何在亚马逊 Linux EC2 上安装 Minikube 和 kubernates
- javascript - 有没有办法用单选按钮和复选框创建 Javascript 过滤器?
- r - 将 ggdend 树与 geom_scatterpie 相结合
- apache-spark - Spark Streaming Job 运行速度很慢
- jenkins - Jenkins 声明式管道中上游多分支作业的最后一次成功构建的修订
- primefaces - PrimeFaces 的修改区域设置消息不起作用
- r - 有没有办法简化/循环栅格堆栈子集?
- c# - UWP如何指定Toast通知的宽度高度