Невозможно обновить реквизиты в дочернем компоненте

#reactjs #handler

#reactjs #обработчик

Вопрос:

Это мой родительский компонент, имеющий состояние (значение и элемент). Я пытаюсь передать состояние значения в качестве реквизита дочернему компоненту. Код, выполняемый в методе рендеринга, выполняет переключение, когда я нажимаю на кнопку. Но когда я вызываю функцию списка внутри componentDidMount, переключение не работает, но выполняется событие щелчка.

 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

  

Это мой дочерний компонент, в котором состояние передается как реквизит

 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
  

Я знаю, что componentDidMount выполняется только один раз. но как заставить его работать, кроме как писать JSX непосредственно внутри метода рендеринга

Комментарии:

1. Спасибо, Рехан, за ответ, таким образом, все работает правильно.

Ответ №1:

создайте копию состояния вместо того, чтобы изменять его напрямую. Используя […this.state.values] или this.state.values.slice()

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

Также в вашем методе рендеринга this.state.item является массивом, поэтому вам нужно выполнить цикл

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

Также непосредственно в вашем методе рендеринга вы можете просто сделать

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

В вашем компоненте card попробуйте использовать

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

Комментарии:

1. Спасибо, Омар, за твой ответ, я внес все изменения, но вопрос в том, что обработчик переключения не работает, когда я отображаю {this.state.item.map(Элемент => <Элемент />} этот код вместо этого {this.state.values.map((данные, индекс)=> { return <Card key = {index} show = {this.state.values[index]} toggleHandler = {() => this.toggleHandler(index)} /> })} Можете ли вы, пожалуйста, подсказать мне, как заставить это работать с первым подходом. Еще раз спасибо.

2. да, я внес одно изменение в свой ответ, если это не решит проблему, я думаю, вам следует воспроизвести ошибку в codesandbox, чтобы я мог напрямую редактировать ваш код. Пожалуйста, взгляните на изменения, которые я внес в функцию toggleHandler Я использую array.filter вместо array.splice

3. codesandbox.io/s/frosty-bohr-v6hxw?file=/src/App.js ссылка на codesandbox

Ответ №2:

Значение должно быть отображено внутри render() компонента класса, чтобы работать

вот так:

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

проверьте песочницу для демонстрации

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