简体   繁体   中英

Unable to update props in child component

This is my parent Component having state ( value and item ). I am trying to pass value state as a props to child component. The code executed in render method is Performing toggle when i click on button. But when i call the list function inside componentDidMount, Toggle is not working but click event is performed.

import React, { Component } from 'react'
import Card from './Components/Card/Card'

export class App extends Component {
  
  state = {
    values : new Array(4).fill(false),
    item : [],
  }

  toggleHandler = (index) => {
    console.log("CLICKED");
    let stateObject = this.state.values;
    stateObject.splice(index,1,!this.state.values[index]);
    this.setState({ values: stateObject });
  }

  list = () => {
    const listItem = this.state.values.map((data, index) => {
      return <Card key = {index} 
        show = {this.state.values[index]} 
        toggleHandler = {() => this.toggleHandler(index)} />
    })
    this.setState({ item : listItem  });
  }

  componentDidMount(){
    // if this is not executed as the JSX is render method is executed everything is working fine. as props are getting update in child component.
    this.list();
  }

  render() {
    
    return (
      <div>
      {/* {this.state.values.map((data, index) => {
        return <Card key = {index} 
          show = {this.state.values[index]} 
          toggleHandler = {() => this.toggleHandler(index)} />
      })
      } */}

      {this.state.item}

      </div>
    )
  }
}

export default App

This is my child Component where the state is passed as props

import React from 'react'

const Card = (props) => {
    return (
        <div>
            <section>
                <h1>Name : John Doe</h1>
                <h3>Age : 20 </h3>
            </section>
            
            {props.show ?
                <section>Skills : good at nothing</section> : null
            }
            <button onClick={props.toggleHandler} >Toggle</button>
        </div>
    )
}

export default Card

I know the componentDidMount is executed only once. but how to make it work except writing the JSX directly inside render method

make a copy of the state instead of mutating it directly. By using [...this.state.values] or this.state.values.slice()

  toggleHandler = (index) => {
    console.log("CLICKED");
    let stateObject = [...this.state.values]
    stateObject = stateObject.filter((_, i) => i !== index);
    this.setState({ values: stateObject });
  }

Also in your render method, this.state.item is an array so you need to loop it

  {this.state.item.map(Element => <Element />}

Also directly in your Render method you can just do

{this.state.values.map((data, index) => {
      return <Card key = {index} 
        show = {this.state.values[index]} 
        toggleHandler = {() => this.toggleHandler(index)} />
    })}

In your card component try using

<button onClick={() => props.toggleHandler()}} >Toggle</button>

Value should be mapped inside render() of the class component in order to work

like this:

 render() {
    const { values } = this.state;
    return (
      <div>
        {values.map((data, index) => {
          return (
            <Card
              key={index}
              show={values[index]}
              toggleHandler={() => this.toggleHandler(index)}
            />
          );
        })}
      </div>
    );
  }

check sandbox for demo

https://codesandbox.io/s/stupefied-spence-67p4f?file=/src/App.js

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