将 React 值从子级传递给父级

IT技术 reactjs rxjs material-ui
2021-05-14 01:31:04

我正在努力解决一些可能非常简单的问题。我的父组件是一个 Search 小部件,它需要使用在单独的 Drawer 组件中定义的过滤器。目前用户可以输入一个搜索查询,它调用一个API,它需要根据抽屉组件的选择器过滤结果。但是,我无法链接父母和孩子来实现这一点!!

父组件(包括其中的 '' 组件):

function SuburbSearch(props: Props) {
    const classes = useStyles();
    const [value, setValue] = React.useState<App.Suburb | null>(null);
    const [inputValue, setInputValue] = React.useState('');
    ...
    
    return (
    <Autocomplete
      id="search"
      getOptionLabel={(option) => (typeof option === 'string' ? option : option.name + ' ' + option.state)}
      filterOptions={(x) => x}
      options={options}
      ...
      ...
      renderInput={(params) => (
        <TextField
          {...params}
          label="Search for a suburb"
          ...,
            startAdornment: (
              <InputAdornment position="start">
                <Filters></Filters>
              </InputAdornment>
            ),
            endAdornment: (
              <React.Fragment>
                {loading ? <CircularProgress color="inherit" size={20} /> : null}
                {params.InputProps.endAdornment}
              </React.Fragment>
            ),
          }}
          fullWidth
        />
      )}

子组件(这是“过滤器”):

export default function Filters() {
  const classes = useStyles();
  const [state, setState] = useState(false);
  const [dollar, setDollars] = useState<number[]>([0, 20000000]);
  const [type, setType] = React.useState<string | null>('all');
  
  ...
  const list = (anchor: Anchor) => (
    <div className={classes.root} 
      role="presentation" /*onClick={toggleDrawer(false)} onKeyDown={toggleDrawer(false)}/*/>
      <Grid className={classes.main} container spacing={2}>
        <Grid className={classes.row} item xs={1} md={2} />
        <Grid className={classes.row} item xs={10} md={8}>
          <Typography className={classes.header} align='center' gutterBottom>
            Property Type
          </Typography>
          <ToggleButtonGroup value={type} onChange={handleTypeChange} exclusive>
            <ToggleButton value="all" >All</ToggleButton>
            <ToggleButton value="some" >Some</ToggleButton>
          </ToggleButtonGroup>
        </Grid>
        ...
      </Grid>
   </div>
}

2个回答

您可以简单地通过将函数作为props传递来完成,如下所示:

父组件

childCallback(value) {
    // value passed from child
}

return {
    <ChildComponent passToParent={this.childCallback}/>
}

子组件

this.props.passToParent(childValue);

在这里,我为您提供了 Pure React 中的一些基本状态管理技术,因为到目前为止我是通过在评论部分与您讨论而了解的。

模式 1,直截了当

假设您有一个组件,comp1即它有一些props,包括一个需要来自其直接子组件的一些数据的方法,例如Comp2

const Comp1 = ({ onActionOrChild }) => {
  return (
    <>
      <Comp2 onAction={onActionOrChild} />
    </>
  )
}

const Comp2 = ({ onAction }) => {
  return (
    <form onSubmit={onAction}>
      ...
    </form>
  )
}

简而言之,这里我们有一个组件需要一些数据,比如说一些表单数据,来自它的一个后代,所以我们将它传递给那个孩子。这里问题Prop 钻孔Comp1需要接收一个它从不使用的props。

模式二,用Context API解决Prop Drilling

现在,react Context API是稳定的,这对于实现过去需要其他状态管理库的东西非常强大。

16.3 版引入了一个新的上下文 API,该 API 更高效并支持静态类型检查和深度更新。-文档

如果我们使用上下文 API,我们可以从组件中提取这些方法并将它们放在一个新文件中,这将创建上下文提供程序,以便应用程序中的不同组件可以相互通信,而无需将 props 传递给组件通过从未使用它的中间组件降低一些级别。

上下文.js

export const AppContext = createContext();

export AppContextProvider = ({children}) => {

  const onAction = () => {}
  return (
    <AppContextProvider.Provider
      value={{onAction}}
    >
    {children}
    </AppContextProvider.Provider>
  )
  
}

现在,如果我们需要在应用程序的任何部分中使用一个方法,我们只需要连接上下文 API

import { AppContext } from "./Context.js"

const comp3 = ({}) => {
  const { onAction } = useContext(AppContext);
  
  return (
    <form onSubmit={onAction}>
    ...
    </form>
  )
}