【问题标题】:How to pass data from child component to its parent in ReactJS?如何在 ReactJS 中将数据从子组件传递到其父组件?
【发布时间】:2018-07-17 07:12:23
【问题描述】:

我正在尝试将数据从子组件发送到其父组件,如下所示:

const ParentComponent = React.createClass({
    getInitialState() {
        return {
            language: '',
        };
    },
    handleLanguageCode: function(langValue) {
        this.setState({language: langValue});
    },

    render() {
         return (
                <div className="col-sm-9" >
                    <SelectLanguage onSelectLanguage={this.handleLanguage}/> 
                </div>
        );
});

这是子组件:

export const SelectLanguage = React.createClass({
    getInitialState: function(){
        return{
            selectedCode: '',
            selectedLanguage: '',
        };
    },

    handleLangChange: function (e) {
        var lang = this.state.selectedLanguage;
        var code = this.state.selectedCode;
        this.props.onSelectLanguage({selectedLanguage: lang});   
        this.props.onSelectLanguage({selectedCode: code});           
    },

    render() {
        var json = require("json!../languages.json");
        var jsonArray = json.languages;
        return (
            <div >
                <DropdownList ref='dropdown'
                    data={jsonArray} 
                    value={this.state.selectedLanguage}
                    caseSensitive={false} 
                    minLength={3}
                    filter='contains'
                    onChange={this.handleLangChange} />
            </div>            
        );
    }
});

我需要的是在父组件中获取用户选择的值。我收到此错误:

Uncaught TypeError: this.props.onSelectLanguage is not a function

谁能帮我找出问题所在?

附:子组件正在从 json 文件创建一个下拉列表,我需要下拉列表来显示 json 数组的两个元素并排显示(例如:“aaa,english”作为首选!)

{  
   "languages":[  
      [  
         "aaa",
         "english"
      ],
      [  
         "aab",
         "swedish"
      ],
}

【问题讨论】:

  • &lt;SelectLanguage onSelectLanguage={this.handleLanguage*Code*}/&gt; 一个错字。
  • @YuryTarabanko 谢谢,但仍然遇到同样的错误
  • @DavinTryon 我应该如何添加它?我试过这样:handleLanguageCode: function(langValue) { this.setState({ language: langValue }).bind(this); }, 但它返回一个错误:ncaught TypeError: Cannot read property 'bind' of undefined
  • @DavinTryon createClass 自动绑定非反应方法。
  • @OP 你能创建一个小提琴来演示这个问题吗?

标签: reactjs


【解决方案1】:

这应该可行。在发送回道具时,您将其作为对象发送,而不是将其作为值发送,或者将其用作父组件中的对象。其次,您需要格式化您的 json 对象以包含名称值对并使用 DropdownListvalueFieldtextField 属性

简答

家长:

<div className="col-sm-9">
     <SelectLanguage onSelectLanguage={this.handleLanguage} /> 
</div>

孩子:

handleLangChange = () => {
    var lang = this.dropdown.value;
    this.props.onSelectLanguage(lang);            
}

详细说明:

编辑:

考虑到 React.createClass 从 v16.0 起已弃用,最好继续通过扩展 React.Component 创建一个 React 组件。使用这种语法将数据从子组件传递到父组件看起来像

父母

class ParentComponent extends React.Component {

    state = { language: '' }

    handleLanguage = (langValue) => {
        this.setState({language: langValue});
    }

    render() {
         return (
                <div className="col-sm-9">
                    <SelectLanguage onSelectLanguage={this.handleLanguage} /> 
                </div>
        )
     }
}

孩子

var json = require("json!../languages.json");
var jsonArray = json.languages;

export class SelectLanguage extends React.Component {
    state = {
            selectedCode: '',
            selectedLanguage: jsonArray[0],
        }

    handleLangChange = () => {
        var lang = this.dropdown.value;
        this.props.onSelectLanguage(lang);            
    }

    render() {
        return (
            <div>
                <DropdownList ref={(ref) => this.dropdown = ref}
                    data={jsonArray} 
                    valueField='lang' textField='lang'
                    caseSensitive={false} 
                    minLength={3}
                    filter='contains'
                    onChange={this.handleLangChange} />
            </div>            
        );
    }
}

使用 OP 在他的回答中使用的 createClass 语法 家长

const ParentComponent = React.createClass({
    getInitialState() {
        return {
            language: '',
        };
    },

    handleLanguage: function(langValue) {
        this.setState({language: langValue});
    },

    render() {
         return (
                <div className="col-sm-9">
                    <SelectLanguage onSelectLanguage={this.handleLanguage} /> 
                </div>
        );
});

儿童

var json = require("json!../languages.json");
var jsonArray = json.languages;

export const SelectLanguage = React.createClass({
    getInitialState: function() {
        return {
            selectedCode: '',
            selectedLanguage: jsonArray[0],
        };
    },

    handleLangChange: function () {
        var lang = this.refs.dropdown.value;
        this.props.onSelectLanguage(lang);            
    },

    render() {

        return (
            <div>
                <DropdownList ref='dropdown'
                    data={jsonArray} 
                    valueField='lang' textField='lang'
                    caseSensitive={false} 
                    minLength={3}
                    filter='contains'
                    onChange={this.handleLangChange} />
            </div>            
        );
    }
});

JSON:

{ 
"languages":[ 

    { 
    "code": "aaa", 
    "lang": "english" 
    }, 
    { 
    "code": "aab", 
    "lang": "Swedish" 
    }, 
  ] 
}

【讨论】:

  • 感谢 Shubham,您的回答解决了这个问题,但它没有在下拉列表中显示所选项目。之后它是空的:/
  • @Sarah 在创建 dropDownList 时,您将其值分配为 this.state.selectedLanguage 并且未初始化为任何值。这可能是问题所在。您使用的是哪个 DropdownList 组件。如果我知道,也许我可以解决这个问题。
  • @Sarah 我对代码做了一些小改动,包括将值绑定到 onChange 函数以及设置初始状态值。试试这个,告诉我它是否适合你
  • @Jesse 功能组件也可以有方法。语法会有所不同,但本质将保持不变。
【解决方案2】:

我找到了如何在需要时从父母的子组件中获取数据的方法。

家长:

class ParentComponent extends Component{
  onSubmit(data) {
    let mapPoint = this.getMapPoint();
  }

  render(){
    return (
      <form onSubmit={this.onSubmit.bind(this)}>
        <ChildComponent getCurrentPoint={getMapPoint => {this.getMapPoint = getMapPoint}} />
        <input type="submit" value="Submit" />
      </form>
    )
  }
}

孩子:

class ChildComponent extends Component{
  constructor(props){
    super(props);

    if (props.getCurrentPoint){
      props.getCurrentPoint(this.getMapPoint.bind(this));
    }
  }

  getMapPoint(){
    return this.Point;
  }
}

这个例子展示了如何将函数从子组件传递给父组件,并使用该函数从子组件获取数据。

【讨论】:

    【解决方案3】:

    将数据从子组件传递到父组件

    在父组件中:

    getData(val){
        // do not forget to bind getData in constructor
        console.log(val);
    }
    render(){
     return(<Child sendData={this.getData}/>);
    }
    

    在子组件中:

    demoMethod(){
       this.props.sendData(value);
     }
    

    【讨论】:

    • 不要忘记构造函数中的this.getData = this.getData.bind(this);,如果你想在getData中操作状态,你可能会得到this.setState不是一个函数。
    【解决方案4】:

    React.createClass 方法在新版本的 React 中已经被弃用了,你可以很简单的做到这一点,方法是让一个功能组件和另一个类组件保持状态:

    家长:

    const ParentComp = () => {
      
      getLanguage = (language) => {
        console.log('Language in Parent Component: ', language);
      }
      
      <ChildComp onGetLanguage={getLanguage}
    };

    孩子:

    class ChildComp extends React.Component {
        state = {
          selectedLanguage: ''
        }
        
        handleLangChange = e => {
            const language = e.target.value;
            thi.setState({
              selectedLanguage = language;
            });
            this.props.onGetLanguage({language}); 
        }
    
        render() {
            const json = require("json!../languages.json");
            const jsonArray = json.languages;
            const selectedLanguage = this.state;
            return (
                <div >
                    <DropdownList ref='dropdown'
                        data={jsonArray} 
                        value={tselectedLanguage}
                        caseSensitive={false} 
                        minLength={3}
                        filter='contains'
                        onChange={this.handleLangChange} />
                </div>            
            );
        }
    };

    【讨论】:

    • 请注意...您应该参考 React 的特定版本而不是“新版本”来证明这个答案。
    【解决方案5】:

    从子组件到父组件如下

    父组件

    class Parent extends React.Component {
       state = { message: "parent message" }
       callbackFunction = (childData) => {
           this.setState({message: childData})
       },
       render() {
            return (
                <div>
                     <Child parentCallback = {this.callbackFunction}/>
                     <p> {this.state.message} </p>
                </div>
            );
       }
    }
    

    子组件

    class Child extends React.Component{
        sendBackData = () => {
             this.props.parentCallback("child message");
        },
        render() { 
           <button onClick={sendBackData}>click me to send back</button>
        }
    };
    

    我希望这个工作

    【讨论】:

      【解决方案6】:

      你甚至可以避免父级的函数直接更新状态

      在父组件中:

      render(){
       return(<Child sendData={ v => this.setState({item: v}) } />);
      }
      

      在子组件中:

      demoMethod(){
         this.props.sendData(value);
      }
      

      【讨论】:

        【解决方案7】:

        这个想法是向孩子发送一个回调,该回调将被调用以返回数据

        使用函数的完整且最小的示例:

        应用程序将创建一个 Child 计算随机数并将其直接发送回父级,父级将console.log 结果

        const Child = ({ handleRandom }) => {
          handleRandom(Math.random())
        
          return <span>child</span>
        }
        
        const App = () => <Child handleRandom={(num) => console.log(num)}/>
        

        【讨论】:

          【解决方案8】:

          考虑到 React Function Components 和使用 Hooks 越来越流行,我将举一个简单的例子来说明如何将数据从子组件传递到父组件

          在父函数组件中,我们将拥有:

          import React, { useState } from "react";
          

          然后

          const [childData, setChildData] = useState("");
          

          并将 setChildData(其工作类似于类组件中的 this.setState)传递给 Child

          return( <ChildComponent passChildData={setChildData} /> )
          

          在子组件中,我们首先获取接收道具

          function ChildComponent(props){ return (...) }
          

          然后你可以像使用处理函数一样传递数据

          const functionHandler = (data) => {
          
          props.passChildData(data);
          
          }
          

          【讨论】:

            【解决方案9】:

            React v16.8+函数组件中,您可以使用useState()创建一个函数状态,让您更新父状态,然后将其作为props属性传递给子组件,然后在子组件内部您可以触发父状态函数,下面是一个工作的sn-p:

            const { useState , useEffect } = React;
            
            function Timer({ setParentCounter }) {
              const [counter, setCounter] = React.useState(0);
            
              useEffect(() => {
                let countersystem;
                countersystem = setTimeout(() => setCounter(counter + 1), 1000);
            
                return () => {
                  clearTimeout(countersystem);
                };
              }, [counter]);
            
              return (
                <div className="App">
                  <button
                    onClick={() => {
                      setParentCounter(counter);
                    }}
                  >
                    Set parent counter value
                  </button>
                  <hr />
                  <div>Child Counter: {counter}</div>
                </div>
              );
            }
            
            function App() {
              const [parentCounter, setParentCounter] = useState(0);
            
              return (
                <div className="App">
                  Parent Counter: {parentCounter}
                  <hr />
                  <Timer setParentCounter={setParentCounter} />
                </div>
              );
            }
            
            ReactDOM.render(<App />, document.getElementById('react-root'));
            <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
            <div id="react-root"></div>

            【讨论】:

              【解决方案10】:

              使用回调将数据从子组件传递到父组件

              You need to pass from parent to child callback function, and then call it in the child.
              

              父组件:-TimeModal

                handleTimeValue = (timeValue) => {
                    this.setState({pouringDiff: timeValue});
                }
              
                <TimeSelection 
                      prePourPreHours={prePourPreHours}
                      setPourTime={this.setPourTime}
                      isPrePour={isPrePour}
                      isResident={isResident}
                      isMilitaryFormatTime={isMilitaryFormatTime}
                      communityDateTime={moment(communityDT).format("MM/DD/YYYY hh:mm A")}
                      onSelectPouringTimeDiff={this.handleTimeValue}
                   />
              

              注意:- onSelectPouringTimeDiff={this.handleTimeValue}

              需要时在子组件中调用道具

               componentDidMount():void{
                    // Todo use this as per your scenrio
                     this.props.onSelectPouringTimeDiff(pouringDiff);  
                }
              

              【讨论】:

                【解决方案11】:

                将数据从子组件传递到父组件的最佳方式

                子组件

                handleLanguageCode=()=>(langValue) {
                  this.props.sendDatatoParent(langValue)
                }
                

                家长

                this.setState({item: data}) } />;

                【讨论】:

                  【解决方案12】:

                  您可以使用 useState 在 ParentComponent 中创建状态,并将 setIsParentData 函数作为 prop 传递给 ChildComponent。

                  在ChildComponent中,通过prop接收到的函数更新数据,将数据发送回ParentComponent。

                  我使用这种技术,尤其是当我在 ParentComponent 中的代码变得太长时,因此我将从 ParentComponent 创建子组件。通常,它只会下降 1 级,并且使用 useContext 或 redux 似乎有点过分了,以便在组件之间共享状态。

                  ParentComponent.js

                  import React, { useState } from 'react';
                  import ChildComponent from './ChildComponent';
                  
                  export function ParentComponent(){
                    const [isParentData, setIsParentData] = useState(True);
                  
                    return (
                      <p>is this a parent data?: {isParentData}</p>
                      <ChildComponent toChild={isParentData} sendToParent={setIsParentData} />
                    );
                  }
                  

                  ChildComponent.js

                  import React from 'react';
                  
                  export function ChildComponent(props){
                  
                    return (
                      <button onClick={() => {props.sendToParent(False)}}>Update</button>
                      <p>The state of isParentData is {props.toChild}</p>
                    );
                  };
                  

                  【讨论】:

                  • 找不到比这更简单和简短的答案了。干得好@Shafie!。
                  【解决方案13】:

                  这里我试图用最简单的方式来解释: 我正在从子组件更新父组件计数器。

                  父组件 (PropsApp.jsx)

                  import React, { useState } from 'react'
                  import Child from './Child'
                  
                  export default function PropsApp(){
                     const [counter, setCounter] = useState(0)
                  
                     const updateMyCounter = () => {
                         setCounter(counter + 1)
                     }
                  
                     return(
                      <>  
                          <hr></hr>
                          <h1>This is Parent</h1>
                          <h2>{counter}</h2>
                          <Child updateParent={updateMyCounter} />
                      </>
                     )
                  }
                  

                  子组件 (Child.jsx)

                  export default function Child(props){
                  
                  return(
                      <>  
                          <hr></hr>
                          <h1>This is Child</h1>
                          <button
                              onClick={props.updateParent}
                          >
                              Update Parent Component
                          </button>
                      </>
                     )
                  }
                  

                  点击更新父组件,看看魔法

                  【讨论】:

                    【解决方案14】:

                    最近发现了一种通过输入实现此目的的简便方法。

                    基本上我只是 useState,然后将 onChange 设置为子组件的道具,它将“value”作为参数并将其放入 useState“setVal”boom 我每次都得到状态更改子 -> 父

                    const Parent = () => {
                      const [val, setVal] = useState("initial value")
                      return(
                        <>
                        <Child onChange={(value)=> setVal(value)}/>
                        <div>{val}</div>
                        </>
                      )
                    };
                    
                    export default Parent;
                    
                    const Child = (props) => {
                      return(
                      <button onClick={() => props.onChange("your value here") }>
                      )
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-01-04
                      • 2020-09-19
                      • 1970-01-01
                      • 2017-04-28
                      相关资源
                      最近更新 更多