#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
компонента:
- Значение, которое ребенок обновит или изменит
- Способ обновления
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