Реагировать — Счетчик передачи данных от дочернего компонента к родительскому

#reactjs

Вопрос:

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

я пытаюсь создать приложение для счетчика, когда щелчок счетчик увеличивается, а щелчок — счетчик уменьшается

у меня есть родительский компонент, подобный этому

 import React, { useState } from 'react';
import ComponentB from './ComponentB'

const ComponentA = () => {
    const [counterB , setCounterB] = useState(0);

    


    return( 
        <div>
            <h1>ComponentB</h1>
            <h3>{counterB}</h3>
            <ComponentB
            add={counterB => setCounterB(counterB)}
            subtract={counterB => setCounterB(counterB)}/>
        </div> );
    
}
 
export default ComponentA;
 

и дочерний компонент, подобный этому

 import React from 'react';

const ComponentB = (props) =>{
    return(
        <div>
        <button onClick={()=> props.add( 1)}> </button>
        <button onClick={()=> props.subtract(-1)}>-</button>
        </div>
    );
}

export default ComponentB
 

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

1. Почему методы для работы со значением, передаваемым от родителя к потомку, заданы здесь в родительском элементе? В React вы хотите, чтобы состояние было ближе всего к тому, где оно обрабатывается. Передача значения для увеличения или уменьшения от родителя к потомку имеет смысл, но передача логики для этого увеличения или уменьшения (во всяком случае, в этом простом примере) не имеет смысла.

Ответ №1:

С

 return( 
    <div>
        <h1>ComponentA</h1>
        <h3>{counterB}</h3>
        <ComponentB
        add={diff => setCounterB(counterB   diff)}
        subtract={diff => setCounterB(counterB   diff)}/>
    </div> );
 

вы передаете функцию diff => setCounterB(counterB diff) в ComponentB as prop.add . Эта функция устанавливает состояние counterB в первый аргумент этой функции. Поэтому при вызове props.add( 1)} кнопки значение counterB устанавливается равным при 1 каждом ее нажатии.

То, что вы хотите, — это добавить 1 к состоянию counterB . Таким образом, вы должны поступить именно так:

 // Get a hook function - only needed for this Stack Snippet
const {useState} = React;

const ComponentA = () => {
    const [counterB , setCounterB] = useState(0);

    return( 
        <div>
            <h1>ComponentA</h1>
            <h3>{counterB}</h3>
            <ComponentB
            add={diff => setCounterB(counterB   diff)}
            subtract={diff => setCounterB(counterB   diff)}/>
        </div> );
    
}

const ComponentB = (props) =>{
    return(
        <div>
        <button onClick={()=> props.add( 1)}> </button>
        <button onClick={()=> props.subtract(-1)}>-</button>
        </div>
    );
}

ReactDOM.render(
  <ComponentA/>,
  document.getElementById("react")
); 
 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3 Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div> 

Ответ №2:

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

 class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
    this.updateCountWithValue = this.updateCountWithValue.bind(this);
  }

  updateCountWithValue(value) {
    let count = this.state.count;
    count  = value;
    this.setState({
      count: count
    });
  }

  render() {
    return (
      <div>
        <h1>{`Count: ${this.state.count}`}</h1>
        <Child updateCount={this.updateCountWithValue} value={1} />
        <Child updateCount={this.updateCountWithValue} value={-1} />
      </div>
    );
  }
}

class Child extends Component {
  render() {
    return (
      <div>
        <button onClick={() => this.props.updateCount(this.props.value)}>
          {this.props.value}
        </button>
      </div>
    );
  }
}
 

Как вы можете видеть, реквизит моего Child компонента:

  1. Значение, которое ребенок обновит или изменит
  2. Способ обновления Parent компонента.

Я сделал этот образец, чтобы вы могли увидеть, как он работает: https://codesandbox.io/s/child-to-parent-uvfmi?file=/src/App.js

Ответ №3:

Вместо этого:

 <ComponentB
   add={counterB => setCounterB(counterB)}
   subtract={counterB => setCounterB(counterB)}/>
 

Попробуйте это:

 <ComponentB
   add={val => setCounterB(counterB val)}
   subtract={val => setCounterB(counterB val)}/>   // using ' ' coz val = -1