【问题标题】:React: Function in Parent Component not receiving data from Child Component反应:父组件中的函数未从子组件接收数据
【发布时间】:2018-08-16 16:30:49
【问题描述】:

我正在使用 React 开发一个项目,我需要使用子组件的输入来更新父组件的 state。我对链中的每个函数都做了console.log(),发现我的父组件中的fetchText() 函数没有收到文本

这是我的父组件的样子

class AppComponent extends React.Component{
  constructor(props){
    super(props);
    this.state = { markdownText: `` };

    this.fetchText = this.fetchText.bind(this);
  }

  fetchText(text){
    this.setState({ markdownText: text });
    console.log(text);
  }

  render(){
    return(
      <div id="app-grid">
        <h1>Markdown Viewer</h1>
        <MarkDownComponent userInput={this.fetchText} />
        <PreviewComponent />
      </div>
    );
  }
}

我的子组件如下所示

class MarkDownComponent extends React.Component{
  constructor(props){
    super(props);
    this.state = { text: ``};

    this.getInput = this.getInput.bind(this);
    this.sendInput = this.sendInput.bind(this);
  }

  getInput(event){
    this.setState({ text: event.target.value });
    this.sendInput();
  }

  sendInput(){
    this.props.userInput = this.state.text;
    //console.log(this.props.userInput);
  }

  render(){
    return(
      <div id="markdown-component">
        <textarea id="editor" rows="16" onChange={this.getInput}></textarea>
      </div>
    );
  }
}

console.log()ing this.props.userInput 在子组件中时,我会在键入时返回值。所以这表明该值正在进入属性,但为什么它不在父组件中更新?

【问题讨论】:

  • 为什么将this.props.userInput分配给this.state.text

标签: reactjs


【解决方案1】:

这里有几点需要注意:

你不能改变 props 的值,它是通过它的 parent 传递给组件的

this.props.userInput = this.state.text;

这行不通。

所以,要让父级的 fetchData 从 textarea 中获取文本,你应该这样做

&lt;textarea id="editor" rows="16" onChange={this.props.userInput}&gt;&lt;/textarea&gt;

在父组件中:

fetchText(event){
    console.log(event.target.value)
    this.setState({ markdownText: event.target.value });
}

您不需要像 getInputsendInput 这样的函数来向父组件发送数据。

【讨论】:

  • @Optiq 希望你清楚,你做错了什么。
【解决方案2】:

问题是您将状态值分配给不正确的函数。

this.props.userInput = this.state.text; // this is incorrect

//Right one

class MarkDownComponent extends React.Component{
  constructor(props){
    super(props);
    this.state = { text: ``};

    this.getInput = this.getInput.bind(this);
    this.sendInput = this.sendInput.bind(this);
  }

  getInput(event){
    this.setState({ text: event.target.value });
    this.sendInput();
  }

  sendInput(){
    this.props.userInput(this.state.text);
    //console.log(this.props.userInput);
  }

  render(){
    return(
      <div id="markdown-component">
        <textarea id="editor" rows="16" onChange={this.getInput}></textarea>
      </div>
    );
  }
}

你可以在getInput函数中直接调用this.props.userInput函数:

class MarkDownComponent extends React.Component{
      constructor(props){
        super(props);
        this.state = { text: ``};

        this.getInput = this.getInput.bind(this);
      }

      getInput(event){
        this.props.userInput(event.target.value);
      }

      render(){
        return(
          <div id="markdown-component">
            <textarea id="editor" rows="16" onChange={this.getInput}></textarea>
          </div>
        );
      }
    }

ES6方式:

class MarkDownComponent extends React.Component{
      constructor(props){
        super(props);
        this.state = { text: ``};
      }

      getInput = (event) => {
        this.props.userInput(this.state.text);
      }

      render(){
        return(
          <div id="markdown-component">
            <textarea id="editor" rows="16" onChange={this.getInput}></textarea>
          </div>
        );
      }
    }

【讨论】:

    【解决方案3】:

    正如 cmets 中所述,无需为您的函数分配状态。此外,如果您希望使用 Child 更改文本,仅此而已,您不需要 Child 中的状态。如果没有必要,不要使用状态。

    class AppComponent extends React.Component {
      constructor(props) {
        super(props);
        this.state = { markdownText: "" };
    
        this.fetchText = this.fetchText.bind(this);
      }
    
      fetchText(e) {
        this.setState({ markdownText: e.target.value});
      }
    
      render() {
        return (
          <div id="app-grid">
            <h1>Markdown Viewer</h1>
            Value is now: {this.state.markdownText}
            <MarkDownComponent userInput={this.fetchText} />
          </div>
        );
      }
    }
    
    const MarkDownComponent = ( props ) => {
      return (
        <div id="markdown-component">
          <textarea id="editor" rows="16" onChange={props.userInput}></textarea>
        </div>
      )
    }
    
    ReactDOM.render(<AppComponent />, document.getElementById("root"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="root"></div>

    【讨论】:

      猜你喜欢
      • 2019-12-09
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 2020-10-02
      • 2019-10-13
      • 1970-01-01
      • 2019-02-17
      相关资源
      最近更新 更多