Pass an object from child to parent component in React

After doing some tutorials and reading the documentation, I try to set up my first response project to try to understand how it all works. Therefore, I am a real beginner, and I have a feeling that I do not understand the fundamental concept.

I had a problem trying to pass an object from a child component to a parent. I managed to pass the object to the parent object, but it cannot then write it to the parent state.

I can very well approach this completely wrong. any guidance will be provided.

I updated my code to now use ref to pass the object to the parent object. However, I assume that refs are only React processes after the HTML is rendered so that it returns the last element in my array of objects, and 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>
Run code
+4
source share
2 answers

Do not use links in this case. You ref (this._obj) are constantly overwritten during the loop. Pass the link to your element to the click handler itself. So change them:

<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 them:

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

_handleClick(obj){
  event.preventDefault();
  this.props.updateContact(obj);
}
+2
source

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

Scenario

, , , , , .. / , ( ), , .

( )

/**
 * 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;

, , , , (Item Component) , onDeleteClick prop . ()

/**
 * 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\ 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;

Item "" , onDeleteClick deleteClickedEvent, . , , , , - , , ,

+2

Source: https://habr.com/ru/post/1661052/


All Articles