[英]How to avoid re-render of React Hooks
嗨,我是 ReactJs 的新开发人员。 我有一个关于 Hooks 的问题。 我知道关于这个任务有很多答案,但我没有将这些解决方案集成到我的项目中。 我有父子组件。 我正在将价值从孩子传递给父母。 当我尝试通过反应回调 function 发送数据时,父级在获取项目时重新渲染,因此我在子级上丢失了我选择的值。 我该如何保护这些问题? 你能给我什么建议吗?
父组件:
import React,{useCallback,useState} from 'react'
const Dropable = ({item}) => {
const [list, setList] = useState(item)
const [selectedItems, setSelectedItems] = useState<Array<any>>([])
const handleSelectedItems = useCallback( (data: any) => {
if (data.type === "player") {
if (selectedItems.length === 0) {
const arr = selectedItems
arr.push(data)
setSelectedItems(arr)
}
}, [selectedItems],
)
return (
{list.map((data: any, index: any) => {
return (
<>
{
<div onClick={() => handleSelectedItems(index, data)}>
<Detailed
key={uuid()}
data={data}
dataIndex={index}
/>
</div>
}
</>
)
})}
)
}
export default Dropable;
子组件:
import React,{useState} from 'react'
const Detailed : React.FC<IProps> = (props) {
const [selected, setSelected] = useState(false)
const handleSelect = () => {
if (selected) {
setSelected(false)
}
else {
setSelected(true)
}
}
return (
<div onClick={handleSelect} className="detail" style={selected?{border: " 1px solid #5c6ef5"}: {}}>
</div>
)
}
export default Detailed;
您可以简单地将selected
的值从父组件传递给子组件,并使用该道具启动选定的 state。
const [selected, setSelected] = useState(props.selected)
那么每次父更新,子选择的state就不会是null了。 您可以通过 null 作为通过道具选择的初始值。 所以,你会这样调用子组件,
import React,{useCallback,useState} from 'react'
const Dropable = ({item}) => {
const [list, setList] = useState(item)
const [selectedItems, setSelectedItems] = useState<Array<any>>([])
const handleSelectedItems = useCallback( (data: any) => {
if (data.type === "player") {
if (selectedItems.length === 0) {
const arr = selectedItems
arr.push(data)
setSelectedItems(arr)
}
}, [selectedItems],
)
return (
{list.map((data: any, index: any) => {
const isSelected = selectedItems.findIndex(item => item.[some_unique_attribute] === data.[some_unique_attribute]) > -1;
return (
<>
{
<div onClick={() => handleSelectedItems(index, data)}>
<Detailed
key={uuid()}
data={data}
dataIndex={index}
selected={isSelected}
/>
</div>
}
</>
)
})}
)
}
嗨,您可以将该值从父级传递给子级,而不是在子级中维护 boolean 值以查看该项目是否被选中。 所以父组件:
const Dropable = ({ item }) => {
const [list, setList] = useState(item)
const [selectedItems, setSelectedItems] = useState<Array<any>>([])
const handleSelectedItems = useCallback((data: any) => {
if (data.type === "player") {
if (selectedItems.length === 0) {
const arr = selectedItems
arr.push(data)
setSelectedItems(arr)
}
}, [selectedItems],
)
return (
{
list.map((data: any, index: any) => {
return (
<>
{
<div onClick={() => handleSelectedItems(index, data)}>
<Detailed
key={uuid()}
data={data}
dataIndex={index}
selected={selectedItems[0][ANY_KEY] === data[ANY_key]}
/>
</div>
}
</>
)
})
}
)
}
export default Dropable;
还有你的子组件:不需要使用 useState 来设置值,因为我们在父组件中做同样的工作。
import React,{useState} from 'react'
const Detailed : React.FC<IProps> = (props) {
return (
<div className="detail" style={props.selected?{border: " 1px solid
#5c6ef5"}: {}}>
</div>
)
}
export default Detailed;
另一个提示:将数据从子组件发送到父组件不是一个好习惯。
当父级重新渲染时,您的子级丢失其 state 的唯一原因是因为您在映射时为子组件分配了一个新键
分配一个唯一但在重新渲染时保持相同的键将防止此问题发生
如果组件的键发生变化,它不会重新渲染而是重新安装,因此 state 值被重置
如果数据中没有唯一键,您可以使用a unique value as key from data
或替代使用index
。 但是,您必须尝试在数据中至少包含 1 个可用于唯一标识它的字段
return (
{
list.map((data: any, index: any) => {
return (
<>
{
<div onClick={() => handleSelectedItems(index, data)}>
<Detailed
key={data.id} // if no id field. You can assign index
data={data}
dataIndex={index}
selected={selectedItems[0][ANY_KEY] === data[ANY_key]}
/>
</div>
}
</>
)
})
}
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.