javascript - 初始渲染时 useState 反应钩子的意外行为
问题描述
我正在构建一个简单的应用程序,该应用程序通过搜索的输入值使用 d3 图显示数据。
export const Search = () => {
const [country, setCountry] = React.useState('');
const [weatherData, setWeatherData] = React.useState([]);
const changeText = e => {
setCountry(e.target.value)
}
const searchCountry = () => {
fetch(`https://apiweatherhistory/dayone/country/${country}`).then(res => res.json().then(data => {
setWeatherData(weatherData)
}))
}
const svg = d3.select('.weatherSearch')
.append('svg')
.attr('width', 960)
.attr('height', 500)
.style('background', 'black')
return (
<div>
<input type='text' onChange={(e) => changeText(e)} value={country} />
<button onClick={searchCountry}>Search</button>
<div className='weatherSearch' />
</div>
)
}
安装组件后,d3 会在 div 标签名称weatherSearch上附加 svg 元素。
问题是组件渲染了两次,然后 svg 标记也被绘制了两次。但是当我注释掉两个状态初始化时,
const [country, setCountry] = React.useState('');
const [weatherData, setWeatherData] = React.useState([]);
该组件仅呈现一次并绘制一次 svg 标签。
输入或点击交互尚未发生,这意味着甚至没有使用两种状态更改方法(setCountry、setWeatherData)。
并且 Search 组件是 index.js 的根组件,因此父组件无法触发重新渲染。
为什么会这样?只有初始化状态才能触发重新渲染?
解决方案
我怀疑这是因为附加 svg 在功能组件主体中,因此每次“渲染”组件时都会执行它。我所说的“渲染”是指,当 React 框架在“渲染”阶段渲染 virtualDOM 树以计算差异时。这与计算 DOM 刷新到实际DOM 以及效果和其他生命周期函数运行时的“提交”阶段不同。“渲染”阶段可以通过几乎任意次数的反应来暂停、中止和重新启动。
我会将这个逻辑放在一个useEffect
带有空依赖数组的钩子中,以便它在组件安装上运行。
export const Search = () => {
const [country, setCountry] = React.useState('');
const [weatherData, setWeatherData] = React.useState([]);
const changeText = e => {
setCountry(e.target.value)
}
const searchCountry = () => {
fetch(`https://apiweatherhistory/dayone/country/${country}`).then(res => res.json().then(data => {
setWeatherData(weatherData)
}))
}
useEffect(() => {
const svg = d3.select('.weatherSearch')
.append('svg')
.attr('width', 960)
.attr('height', 500)
.style('background', 'black');
}, []);
return (
<div>
<input type='text' onChange={(e) => changeText(e)} value={country} />
<button onClick={searchCountry}>Search</button>
<div className='weatherSearch' />
</div>
)
}
推荐阅读
- javascript - 无法将值输入到不可见的网格
- gdb - 使用 --args 选项时重定向 gdb 的输出
- python - 按键时python追加到列表
- typescript - 我可以在条件类型中保留泛型吗?
- fullcalendar - Fullcalendar 将某天的事件转移到某些客户身上
- c++ - 在 C++ 中实现虚函数和运行时多态性时的编译时错误
- javascript - 错误:podfile 更新后 `Podfile` 中的 `React` 具有不同来源的多个依赖项
- python - GITHUB API 技术问题
- powerbi - 动态切片器选择项目 DAX
- reactjs - 将道具传递给 createMaterialTopTabNavigator 中的所有选项卡的问题