【问题标题】:how to call child component's method from parent component's event in ReactjsReactjs中如何从父组件的事件中调用子组件的方法
【发布时间】:2019-11-11 01:03:39
【问题描述】:

您好,我正在尝试将方法从父组件调用到子组件。

我研究了很多我没有得到任何关于孩子(功能组件)的好的解决方案。如果有解决方案可以解释我解决这个问题。

APP.js

     import React from 'react';
        import IntegrationDownshift from './members'
        class App extends React.Component {
             constructor(props) {
              super(props);
              this.state = {
                 Name: "Name from state...",
                 Description: "Description from state...",
                Data:[data]
              }
           }
           Clear(){
    this.IntegrationDownshift.ClearRecord();     // Here I'm trying to call the method on such event  

 }
          render() {  
             return (
                <div>
         <IntegrationDownshift Members={this.state.Data}/>
          <Button variant="contained" color="secondary"  onClick={this.Clear.bind(this)} >  // when i click the button it will trigger
        clear         // when i click the button it will trigger
      </Button>
               </div>
             );
          }
        }

    export default App;`

成员

    var suggestions = []
    var members=[];
    function renderInput(inputProps) {
      const { InputProps, classes, ref, ...other } = inputProps;
      return (
        <TextField
          InputProps={{
            inputRef: ref,
            classes: {
              root: classes.inputRoot,
              input: classes.inputInput,
            },
            ...InputProps,
          }}
          {...other}
        />
      );
    }
    function renderSuggestion(suggestionProps) {
      const { suggestion, index, itemProps, highlightedIndex, selectedItem } = suggestionProps;
      const isHighlighted = highlightedIndex === index;
      const isSelected = (selectedItem || '').indexOf(suggestion.label) > -1;
      return (
        <MenuItem
          {...itemProps}
          key={suggestion.label}
          selected={isHighlighted}
          component="div"
          style={{
            fontWeight: isSelected ? 500 : 400,
          }}
        >
          {suggestion.label}
        </MenuItem>
      );
    }
    renderSuggestion.propTypes = {
      highlightedIndex: PropTypes.number,
      index: PropTypes.number,
      itemProps: PropTypes.object,
      selectedItem: PropTypes.string,
      suggestion: PropTypes.shape({ label: PropTypes.string }).isRequired,
    };
    function getSuggestions(value, { showEmpty = false } = {}) {
      const inputValue = deburr(value.trim()).toLowerCase();
      const inputLength = inputValue.length;
      let count = 0;
      return inputLength === 0 && !showEmpty
        ? []
        : suggestions.filter(suggestion => {
            const keep =
              count < 5 && suggestion.label.slice(0, inputLength).toLowerCase() === inputValue;
            if (keep) {
              count += 1;
            }
            return keep;
          });
    }
    function DownshiftMultiple(props) {
        suggestions=props.Members;
      const { classes } = props;
      const [inputValue, setInputValue] = React.useState('');
      const [selectedItem, setSelectedItem] = React.useState([]);
      function handleKeyDown(event) {
        if (selectedItem.length && !inputValue.length && event.key === 'Backspace') {
          setSelectedItem(selectedItem.slice(0, selectedItem.length - 1));
        }
      }
       function ClearRecord(){     // ** trying to call this function **
       setSelectedItem(selectedItem.slice(0, selectedItem.length - selectedItem.length));
  }

      function handleInputChange(event) {
        setInputValue(event.target.value);
      }
      function handleChange(item) {
        let newSelectedItem = [...selectedItem];
        if (newSelectedItem.indexOf(item) === -1) {
          newSelectedItem = [...newSelectedItem, item];
          members=newSelectedItem;   // **want to send this**
           props.onDataChanged(members)// **here i'm trying to send the value**
        }
        setInputValue('');
        setSelectedItem(newSelectedItem);
      }    
      const handleDelete = item => () => {
        const newSelectedItem = [...selectedItem];
        newSelectedItem.splice(newSelectedItem.indexOf(item), 1);
        setSelectedItem(newSelectedItem);
      };    
      return (
        <Downshift
          id="downshift-multiple"
          inputValue={inputValue}
          onChange={handleChange}
          selectedItem={selectedItem}
        >
          {({
            getInputProps,
            getItemProps,
            getLabelProps,
            isOpen,
            inputValue: inputValue2,
            selectedItem: selectedItem2,
            highlightedIndex,
          }) => {
            const { onBlur, onChange, onFocus, ...inputProps } = getInputProps({
              onKeyDown: handleKeyDown,
              placeholder: 'Select multiple Members',
            });

            return (
              <div className={classes.container}>
                {renderInput({
                  fullWidth: true,
                  classes,
                  InputLabelProps: getLabelProps(),
                  InputProps: {
                    startAdornment: selectedItem.map(item => (
                      <Chip
                        key={item}
                        tabIndex={-1}
                        label={item}
                        className={classes.chip}
                        onDelete={handleDelete(item)}
                      />
                    )),
                    onBlur,
                    onChange: event => {
                      handleInputChange(event);
                      onChange(event);
                    },
                    onFocus,
                  },
                  inputProps,
                })}

                {isOpen ? (
                  <Paper className={classes.paper} square>
                    {getSuggestions(inputValue2).map((suggestion, index) =>
                      renderSuggestion({
                        suggestion,
                        index,
                        itemProps: getItemProps({ item: suggestion.label }),
                        highlightedIndex,
                        selectedItem: selectedItem2,
                      }),
                    )}
                  </Paper>
                ) : null}
              </div>
            );
          }}
        </Downshift>
      );
    }

    DownshiftMultiple.propTypes = {
      classes: PropTypes.object.isRequired,
    };

    const useStyles = makeStyles(theme => ({
      root: {
        flexGrow: 1,
        height: 250,
      },
      container: {
        flexGrow: 1,
        position: 'relative',
      },
      paper: {
        position: 'absolute',
        zIndex: 1,
        marginTop: theme.spacing(1),
        left: 0,
        right: 0,
      },
      chip: {
        margin: theme.spacing(0.5, 0.25),
      },
      inputRoot: {
        flexWrap: 'wrap',
      },
      inputInput: {
        width: 'auto',
        flexGrow: 1,
      },
      divider: {
        height: theme.spacing(2),
      },
    }));

    let popperNode;

    export default function IntegrationDownshift(props) {
        debugger
      const classes = useStyles();
      const Members=props.Members;
       props.onDataChanged("test")

      return (
        <div className={classes.root}>

          <DownshiftMultiple classes={classes} Members={Members}  />

        </div>
      );
    }

我正在尝试实现这个 https://codesandbox.io/s/runh6 功能,它是物质 UI。我无法从父母到孩子调用该方法。 在此操作中,我试图清除 app.js 点击事件中的记录。有没有办法清除app.js中的数据。

【问题讨论】:

    标签: reactjs material-ui react-component


    【解决方案1】:

    React 并没有真正做到这一点。您需要实现的是具有 selectedItem 状态的父级,然后通过 props 将其传递给子级。任何更新此值的函数都需要作为 prop 回调函数从父级传递给子级。这样,父级就拥有了控制子级所需的所有功能,而子级只需渲染通过 props 传入的内容。

    【讨论】:

      【解决方案2】:

      实际上,这些父子组件结构并不符合react的思路。 ReactJS 只推荐从父母到孩子的单向处理。 不过不用担心。

      您可以通过使用父级中的state值以及使用props将父级函数传递给子级的方法来解决这个问题。

      App.js

      this.state = {
         Name: "Name from state...",
         Description: "Description from state...",
         Data:[data],
         resetFlag: false,
      }
      ...
      setReset = () => {
         this.setState(prevState => ({ resetFlag: !prevState.resetFlag }));
      };
      ...
      // this.IntegrationDownshift.ClearRecord(); you can't call children's function directly
      if(!this.state.resetFlag) {
         this.setReset();
      }
      ...
      // then pass state value and function to child.
      <IntegrationDownshift Members={this.state.Data} resetFlag={this.state.resetFlag} setReset={this.setReset}/>
      
      

      成员

      function DownshiftMultiple(props) {
      ...
         // hook props changes
         React.useEffect(() => {
           // component updated
           if(props.resetFlag) {
              // This is the place where you can clear your data
              ClearRecord();
              // set resetFlag as false to prevent erasing your data again.
              props.setReset();
           } 
         });
      

      【讨论】:

      • 你又救了我安东尼奥。谢谢
      • @Vinoth 哈哈,我很高兴。 :D
      • 您的评论是不是有问题?他确实询问了从父母那里调用child.x(),而不是将父母的功能传递给孩子。
      猜你喜欢
      • 2017-11-24
      • 1970-01-01
      • 2016-12-08
      • 2020-06-15
      • 2020-04-16
      • 2020-05-19
      • 2021-05-02
      相关资源
      最近更新 更多