reactjs - Reactjs 从父级更新状态来自子级,而无需重新渲染父级
问题描述
我是使用 reactjs 的初学者。现在我有一个优化我的 reactjs 项目的情况。我有一个来自 material-ui 的自动完成组件,我将它与我的父组件分开,这样我的自动完成的任何关键更改都不会导致重新渲染我的整个父组件。现在我的问题是将我的状态从我的子组件更新到父组件,因为它会重新渲染,包括我的父组件。关于如何避免重新渲染父组件的任何提示?我的目标是不可能的场景吗?对于像我这样的初学者如何优化从孩子到父母的传递/更新状态的建议/答案,我们将不胜感激。
我知道该setState
功能会导致重新渲染。在我的父组件中,如何避免在函数setState
内部使用,SearchTrainingData
以便它不会重新渲染,另一方面它会更新我的状态?我的父组件具有以下功能:
import SearchTraining from '../components/training/SearchTraining';
const Parent = () => {
const SearchTrainingData = (index) => {
// console.log(index);
setState((prev) => ({
...prev,
trainingTitle: index,
}));
};
return (
<>
<SearchTraining SearchTrainingData={SearchTrainingData} />
</>
)
}
这是我的子组件,它使用props.SearchTrainingData
将我的更新状态从我的子组件传递给父组件?
const SearchTraining = (props) => {
const onChangeAutoComplete = (key, val) => {
console.log(key);
props.SearchTrainingData(val);
};
return (
<Autocomplete
freeSolo
disabled={
selectedRecord && selectedRecord.conducted_training.locked
}
options={!selectedRecord ? state.trainingConductList : []}
getOptionLabel={(option) =>
option.title && option.title.title
? option.title.title
: state.trainingTitle
}
getOptionSelected={(o, v) => o.id === v.id}
value={state.training}
renderOption={(option) => (
<ListItemText
primary={
<>
<Box>
<Typography align="right">
<Button
onClick={() => {
setState((prev) => ({
...prev,
newTrainingConduct: true,
isClicked: true,
}));
}}
>
Not what you're looking for?
</Button>
</Typography>
</Box>
<Typography variant="body1" component="p">
{option.title.title}
</Typography>
</>
}
secondary={
<>
<Box mt={1} mb={1}>
<Typography
variant="body2"
component="p"
color="textSecondary"
>
CONDUCTED BY:
</Typography>
<Typography
variant="overline"
component="p"
color="textPrimary"
>
{option.conducted_by.name}
</Typography>
</Box>
<Box mt={1}>
<Typography
variant="caption"
color="textSecondary"
component="p"
>
{option.from_date} - {option.to_date}
</Typography>
</Box>
<Box mt={1} mb={1}>
<Typography
variant="caption"
color="textSecondary"
component="p"
>
Duration (hours): {option.total_hours}{' '}
{option.total_hours <= 1 ? ' hour' : ' hours'}
</Typography>
</Box>
<Divider />
</>
}
/>
)}
onChange={(e, i) => {
e.persist();
if (i) {
onChangeAutoComplete('training', i);
}
}}
/>
)
}
解决方案
您可以使用 ref 代替 state。使用 refs 可以避免在某些值更新后重新渲染组件。
在父组件中:
const ref=useRef(null)
const changeRef=(value)=>{ ref.current=value }
现在不是将 state 和 setState 传递给 Child,而是传递 ref 并更改 Ref。(或者您可以将 changeRef 放在 SearchTrainingData 中,这取决于您)
在子组件中:
const onChangeAutoComplete = (key, val) => {
console.log(key);
props.changeRef(val);
};
在自动完成中:
value={props.ref.current}
推荐阅读
- python - KeyError:'SQLALCHEMY_TRACK_MODIFICATIONS'
- api - 如何搜索 amadeus api 单程航班。任何想法
- amazon-web-services - 带有fluentbit的aws fargate和firelens,ES输出插件TCP连接随机失败
- javascript - 如果已填充或为空,则设置类
- c++ - 按特定顺序迭代数组元素
- html - 如何在 3 列布局中拥有一个固定宽度的居中列?
- javascript - ng 测试后,业力看不到测试(已执行 0 次,共 0 次成功)
- node.js - OpenFire 服务器不适用于 websockets
- windows - 当前目录在批处理脚本中的“CALL”之后自动更改为上一个目录
- dart - 如何在 Dart 的 const 构造函数中断言类型参数不是“动态的”?