最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Pass an object from child to parent component in React - Stack Overflow

programmeradmin4浏览0评论

After doing some tutorials and reading the documentation, I'm trying to setup my first react project to try and get a real understanding of how it all works. So I'm a real beginner at this, And I have a feeling I'm not grasping a fundamental concept.

I'm having an issue trying to pass an object from a child ponent to it's parent. I've managed to pass the object to the parent, but can't then write it to the parent's state.

I may well be approaching this in pletely the wrong way. any guidance would be apricated.

I've updated my code to now use a ref to pass the object to the parent However, I assuming because the refs are only processes by React after the HTML is rendered its allways passing back the last item in my object array not the one i want to associate with each selection.

class AppContainer extends React.Component { //parent Component
  constructor() {
    super();

    this.state = {
      contactsList:
        [
          {id:1, name: 'Tom Brace', phone: '0123456789', address:'fg dfgh dfgh dfgh dfgh', notes: 'sdfdsfasdfasdf asdf as df asdf  sadf a sdfasdf', Quote:''},

         ...

          {id:7, name: 'Dave Johnson', phone: '0123456789', address:'fg dfgh dfgh dfgh dfg', notes: 'sdfdsfasdfasdf asdf as df asdf  sadf a sdfasdf', Quote:''}
        ],
        selectedContact: {id:1, name: 'Tom Brace', phone: '0123456789', address:'fg dfgh dfgh dfgh dfg', notes: 'sdfdsfasdfasdf asdf as df asdf  sadf a sdfasdf', Quote:''}
    }
  }

  render(){
    return(
      <div className="container-fluid">
        <div className="row">
          <div id="sidebar" className="col-xs-12 col-md-3 sidebar">
             <ContactNav updateContact={this._updateContact.bind(this)}
                          contactsList={this.state.contactsList}
                        />
                      </div>
                      <div id="content" className="col-xs-12 col-md-9 main">
                        <Content
                          selectedContact={this.state.selectedContact}
                        />
                      </div>
                    </div>
                  </div>
                );
              };

              _updateContact(obj){
  console.log(obj)
                this.setState({
                selectedContact: obj
              });
              }
            }

            class ContactNav extends React.Component { //child of AppContainer

              render() {
                const contacts = this._getContacts() || [];
                return(
                  <div>
                    <div className="input-group">
                      <input type="text" className="form-control" placeholder="Search for..." />
                      <span className="input-group-btn">
                        <button className="btn btn-default" type="button">Go!</button>
                      </span>
                    </div>
                    <ul className="nav nav-sidebar">
                      {contacts}
                    </ul>
                  </div>
                );
              }
              _handleClick(){
                event.preventDefault();
console.log(this._obj);
                let obj = this._obj
                this.props.updateContact(obj);
              }


              _getContacts() {
                return this.props.contactsList.map((i) => {
                  return (
                    <li key={i.id}>
                      <a href="#" key={i.id} onClick={this._handleClick.bind(this)} ref={(input) => this._obj = i}>
                        {i.name}
                      </a>
                    </li>
                  );
                });
              }
            }

            class Content extends React.Component { //child of AppContainer
              render() {
                return(
                  <div>
                    <h1 className="page-header">{this.props.selectedContact.name}</h1>
                    <h3 className="sub-header">{this.props.selectedContact.phone}</h3>
                    <h6 className="sub-header">{this.props.selectedContact.address}</h6>
                    <h6 className="sub-header">{this.props.selectedContact.notes}</h6>
                  </div>
                );
              }
            }


            ReactDOM.render(
              <AppContainer />, document.getElementById('app')
            );
html, body, #app, .container-fluid, .row {
  height: 100%;
}
.sidebar {
    z-index: 1000;
    display: block;
    padding: 20px;
    overflow-x: hidden;
    overflow-y: auto;
    background-color: #f5f5f5;
    border-right: 1px solid #eee;
		height:100%;
}
.active {
  background-color: blue;
  color: white;
}
<script src=".1.0/react.min.js"></script>
<script src=".1.0/react-dom.min.js"></script>
<link rel="stylesheet" href=".3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<div id="app">
      </div>

After doing some tutorials and reading the documentation, I'm trying to setup my first react project to try and get a real understanding of how it all works. So I'm a real beginner at this, And I have a feeling I'm not grasping a fundamental concept.

I'm having an issue trying to pass an object from a child ponent to it's parent. I've managed to pass the object to the parent, but can't then write it to the parent's state.

I may well be approaching this in pletely the wrong way. any guidance would be apricated.

I've updated my code to now use a ref to pass the object to the parent However, I assuming because the refs are only processes by React after the HTML is rendered its allways passing back the last item in my object array not the one i want to associate with each selection.

class AppContainer extends React.Component { //parent Component
  constructor() {
    super();

    this.state = {
      contactsList:
        [
          {id:1, name: 'Tom Brace', phone: '0123456789', address:'fg dfgh dfgh dfgh dfgh', notes: 'sdfdsfasdfasdf asdf as df asdf  sadf a sdfasdf', Quote:''},

         ...

          {id:7, name: 'Dave Johnson', phone: '0123456789', address:'fg dfgh dfgh dfgh dfg', notes: 'sdfdsfasdfasdf asdf as df asdf  sadf a sdfasdf', Quote:''}
        ],
        selectedContact: {id:1, name: 'Tom Brace', phone: '0123456789', address:'fg dfgh dfgh dfgh dfg', notes: 'sdfdsfasdfasdf asdf as df asdf  sadf a sdfasdf', Quote:''}
    }
  }

  render(){
    return(
      <div className="container-fluid">
        <div className="row">
          <div id="sidebar" className="col-xs-12 col-md-3 sidebar">
             <ContactNav updateContact={this._updateContact.bind(this)}
                          contactsList={this.state.contactsList}
                        />
                      </div>
                      <div id="content" className="col-xs-12 col-md-9 main">
                        <Content
                          selectedContact={this.state.selectedContact}
                        />
                      </div>
                    </div>
                  </div>
                );
              };

              _updateContact(obj){
  console.log(obj)
                this.setState({
                selectedContact: obj
              });
              }
            }

            class ContactNav extends React.Component { //child of AppContainer

              render() {
                const contacts = this._getContacts() || [];
                return(
                  <div>
                    <div className="input-group">
                      <input type="text" className="form-control" placeholder="Search for..." />
                      <span className="input-group-btn">
                        <button className="btn btn-default" type="button">Go!</button>
                      </span>
                    </div>
                    <ul className="nav nav-sidebar">
                      {contacts}
                    </ul>
                  </div>
                );
              }
              _handleClick(){
                event.preventDefault();
console.log(this._obj);
                let obj = this._obj
                this.props.updateContact(obj);
              }


              _getContacts() {
                return this.props.contactsList.map((i) => {
                  return (
                    <li key={i.id}>
                      <a href="#" key={i.id} onClick={this._handleClick.bind(this)} ref={(input) => this._obj = i}>
                        {i.name}
                      </a>
                    </li>
                  );
                });
              }
            }

            class Content extends React.Component { //child of AppContainer
              render() {
                return(
                  <div>
                    <h1 className="page-header">{this.props.selectedContact.name}</h1>
                    <h3 className="sub-header">{this.props.selectedContact.phone}</h3>
                    <h6 className="sub-header">{this.props.selectedContact.address}</h6>
                    <h6 className="sub-header">{this.props.selectedContact.notes}</h6>
                  </div>
                );
              }
            }


            ReactDOM.render(
              <AppContainer />, document.getElementById('app')
            );
html, body, #app, .container-fluid, .row {
  height: 100%;
}
.sidebar {
    z-index: 1000;
    display: block;
    padding: 20px;
    overflow-x: hidden;
    overflow-y: auto;
    background-color: #f5f5f5;
    border-right: 1px solid #eee;
		height:100%;
}
.active {
  background-color: blue;
  color: white;
}
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn./bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<div id="app">
      </div>

Share Improve this question edited Nov 17, 2016 at 15:27 Pineda 7,5933 gold badges33 silver badges47 bronze badges asked Nov 17, 2016 at 12:24 Thomas BraceThomas Brace 431 silver badge5 bronze badges 2
  • 1 Add a prop to your child ponent that will accept a function reference and call this function with necessary value as parameter. – Rajesh Commented Nov 17, 2016 at 12:26
  • Have you tried onClick={this.updateContact.bind(this)} for the ContactNav click handler? – tommy Commented Nov 17, 2016 at 13:40
Add a ment  | 

2 Answers 2

Reset to default 3

You can pass it through as props. I will take a simple example for passing objects from child to parent ponent

Scenario

Let's say we have multiple card item to be displayed and each of them have its ID, Name, Date etc attributes. Each of the card item has delete functionality/operation, we can take this delete operation as a ponent (which will be a child ponent of the item ponent) lets see how we can pass values to the parent from the child.

Lets 1st see the child ponent (Delete Component)

/**
 * Delete ponent
 */

import * as React from 'react';
import { IconButton, Button } from 'react-toolbox/lib/button';


interface IDeleteProps {
    onDeleteClick: (e:boolean) => void;
}


class Delete extends React.Component<IDeleteProps, {}> {

    constructor(props) {
        super(props);
    }
    public onClickTrigger = () => {
        this.props.onDeleteClick(true);
    }
    public render() {
        return (

            <Button icon='inbox' label='Delete' onClick={this.onClickTrigger} flat primary />

        );
    }
}

export default Delete;

Here you can see we are trying to check whether the button is clicked or not, and main intention is to notify the parent ponent (Item Component) to do further process, onDeleteClick method here is used as a prop to pass the boolean value to parent ponent, Now lets see the Parent Component (Item)

/**
 * Item ponent
 */

import * as React from 'react';
import './styes.scss';
import Edit from '../item/operation/Edit';
import Delete from '../item/operation/Delete';
import View from '../item/operation/View';
const ReactGauge = require('react-gauge').default;

interface IItemProps {
    item: any;
    onDeleteChangeItem: (id: number) => void;
}


class Item extends React.Component<IItemProps, {}> {

    constructor(props) {
        super(props);
    }
    public deleteClickedEvent = (e: boolean) => {
        if (e === true) {
            this.props.onDeleteChangeItem(this.props.item.id);
        }
    }

    public render() {
        const dummyText = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.';
        const itemStyle = {
            backgroundImage: `url('${this.props.item.url}')`
        };

        return (
            <div style={itemStyle} className='AudienceGridItem'>

                <span className='name'>{this.props.item.id}</span>
                <span className='name'>{this.props.item.name}</span>
                <span className='name'>{this.props.item.customerCount}</span>
                <span className='name'>{this.props.item.lastEdited}</span>
                <span className='name'>{this.props.item.lastRerun}</span>
                <ReactGauge
                    value={this.props.item.percentage}
                    width={140} height={70}
                    />
                <Edit />
                <Delete onDeleteClick={this.deleteClickedEvent} />
                <View />
            </div>

        );
    }
}

export default Item;

You could see in the Item ponent, Delete ponent is called in the render method and onDeleteClick is called and assigned to a method deleteClickedEvent where within that method it checks the boolean value passed and progress accordingly. This was my example which i tried when i was learning parent children ponent interactions in react, Hope this helped you to understand to some-level, if i am not making any sense please point me out

Don't use refs in this case. You ref (this._obj) is getting continually overwritten during your loop. Pass a reference to your item to the click handler itself. So, change these:

<a href="#" key={i.id} onClick={this._handleClick.bind(this) } ref={(input) => this._obj = i}>
  {i.name}
</a>

_handleClick(){
  event.preventDefault();
  console.log(this._obj);
  let obj = this._obj
  this.props.updateContact(obj);
}

to these:

<a href="#" key={i.id} onClick={() => this._handleClick(i) }>
  {i.name}
</a>

_handleClick(obj){
  event.preventDefault();
  this.props.updateContact(obj);
}
发布评论

评论列表(0)

  1. 暂无评论