如何在Reactjs中从父组件的事件中调用子组件的方法

时间:2019-06-29 12:40:40

标签: reactjs material-ui react-component

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

我已经进行了很多研究,但孩子(功能组件)没有得到任何好的解决方案。如果有解决方案,有什么可以解释我的解决方案。

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 click事件中的记录。有没有一种方法可以清除app.js中的数据。

2 个答案:

答案 0 :(得分:1)

实际上,这些父级和子级组件结构不适合react的想法。 ReactJS仅建议从父母到孩子的单向处理。 但是不用担心。

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

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();
     } 
   });

答案 1 :(得分:0)

React并不能真正做到这一点。您需要实现的是父项的selectedItem处于其状态,然后通过道具将其传递给子项。任何更新此值的函数都必须作为prop回调函数从父级传递到子级。这样,父级便具有控制子级所需的所有功能,而子级仅呈现通过道具传递的内容。