简体   繁体   中英

How do I pass props from child to parent in React?

I have a dynamic table that renders a list of items that the user selects. The user can select an item from a drop down menu and then add that item to the list. As of right now I store the item list in the state of my component, which allows the table to render dynamically. What I would like is for the user to be able to click on an item in the table and be able to edit certain parts of that item, such as the quantity that they are selecting. Once the user clicks on that item from the table a Modal will appear that gets filled with the information from that specific item. My problem is that within the modal, when the user changes say the quantity of that item, I would like the Modal to close and then update the table with that value that the user changed.

Is there a way to pass this updated list of items back to the parent? Or is this not viable? and if so, what would be the right way to go about this. I will post my code below so that you guys can get a better understanding about what I'm trying to accomplish.

NOTE My modal isn't complete but I just would like to know how I can pass props back to the parent component.

Parent.js


export default Parent extends React.Component{
 constructor(props){
  super(props);
   this.state = {
    ItemList = [],
    IDClicked = "",
   }

AddItemHandler(){
...stuff to add to ItemList

}

RenderModal(){
 let itemList = this.state.ItemList

 <ItemModal items={itemList} />
}

RowClick(e){
        //console.log(e.target.id)
        var items = this.state.ItemList;

        for(let i = 0; i < items.length; i++){
            if(items[i].ID == e.target.id){
                var Item = {
                    ID: items[i].ID,
                    PartName: items[i].PartName,
                    Quantity: items[i].Quantity   
                }
            }
        }
        //console.log("Item clicked: " + JSON.stringify(Item));
        this.setState({IDClicked: e.target.id})
        (document.getElementById('myModal')).style.display = "block";
    }

RenderTable(items){
        var rows = [];

        for(let i = 0; i < items.length; i++){
                    rows.push(
                        <tr style={{backgroundColor: '#B7BCDF'}} id={items[i].ID} key={i}>
                            <td style={{maxWidth: '20px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}} onClick={this.RowClick.bind(this)} id={items[i].ID}>
                                {items[i].PartName}
                            </td>

                            <td  style={{maxWidth: '20px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}} onClick={this.RowClick.bind(this)} id={items[i].ID}>
                                {items[i].Description}
                            </td>

                            <td  style={{maxWidth: '20px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}} onClick={this.RowClick.bind(this)} id={items[i].ID}>
                                {items[i].Type}
                            </td>

                            <td  style={{maxWidth: '20px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}} onClick={this.RowClick.bind(this)} id={items[i].ID}>
                                {items[i].Quantity}
                            </td>

                            <td  style={{maxWidth: '20px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}} onClick={this.RowClick.bind(this)} id={items[i].ID}>
                                {items[i].Units}
                            </td>
                        </tr>
                    )      
        }
        return (

            <div className="TableScroll2" style={{width: '99.5%', height: 'none'}}>
                <table className="TableRows">
                    <tbody>
                        {rows}
                    </tbody>
                </table>
            </div>

        );
    }

render(){
 return(
   <div id="mymodal">
    this.RenderModal();
   </div>

   <div style={{width: '50%', marginLeft: 'auto', marginRight: 'auto'}}>
                    <div className="ParTableContainer" style={{marginTop: '5%'}}>
                        <table className="PartTableHeaderContainer" style={{textAlign: 'center'}}>
                            <thead>
                                <tr>
                                    <th style={{width: '20%'}}>Part Name</th>
                                    <th style={{width: '20%'}}>Description</th>
                                    <th style={{width: '20%'}}>Type</th>
                                    <th style={{width: '20%'}}>QTY</th>
                                    <th style={{width: '20%'}}>U/M</th>
                                </tr>
                            </thead>
                        </table>
                    </div>

                    {this.RenderTable(this.state.ItemList)}
                </div>
  <button style={{marginTop: '2%', marginBottom: '5%'}} onClick={this.AddItemHandler.bind(this)}>Add Item</button>
 }
}

You cannot pass props from a child to the parent. There are however ways for a child to communicate with it's parent, which could be used to solve your problem.

The way to go is usually to use callbacks - pass a function from your parent to your child which the child can call to update the state of the parent. Here is an example that updates the parent state:

function Parent() {
    const [counter, setCounter] = useState(0)
    return (
        <div>
            Current: {state}
            <Child increment={() => {
                setCounter(current => current + 1)
            }}}/>
        </div>
    )
}

function Child(props) {
    return <button onClick={props.increment}>Click me</button>
}

(This example was done using hooks, which I strongly recommend learning)

Here it is without hooks:

class Parent extends Component {
    constructor() {
        this.state = { counter: 0 }
    }
    render() {
        return (
            <Child increment={() => {
                this.setState((current) => {
                    return { counter: current.counter + 1 }
                })
            }}}/>
        )
    }
}

function Child(props) {
    return <button onClick={props.increment}>Click me</button>
}

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