简体   繁体   中英

Pass an object from child to parent component in React

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 component 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 completely 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.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> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <div id="app"> </div> 

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

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 component (which will be a child component of the item component) lets see how we can pass values to the parent from the child.

Lets 1st see the child component (Delete Component)

/**
 * Delete component
 */

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 component (Item Component) to do further process, onDeleteClick method here is used as a prop to pass the boolean value to parent component, Now lets see the Parent Component (Item)

/**
 * Item component
 */

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 component, Delete component 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 component 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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM