首页 > 解决方案 > 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&apos;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);
        }
        }}
        />
    )
    
}

标签: reactjsreact-functional-component

解决方案


您可以使用 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}

推荐阅读