我刚接触React Js,对于以下情况我确实感到困惑。我的父组件中有一个名为availableShops
的数组,我只是使用 setState 在子组件中对其进行了更新。我也想在子组件中保留setState方法。
父母:
import React, { Component } from 'react';
import Child from './shop-with-price';
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {
availableShops:[]
}
}
render{
return (
<div>
<Child
shops = {this.state.shops}
onChange = {this.handleInputChange}
avalilableShops = {this.state.avalilableShops}
/>
</div>
);
}
}
子组件
import React, { Component } from 'react';
export default class Child extends Component {
constructor(props) {
super(props);
this.state = {
avalilableShops: this.props.avalilableShops,
}
}
handleInputChange(e) {
const target = e.target;
const name = target.name;
const value = target.value;
this.setState({
[name]: value
});
}
createShops(e){
e.preventDefault();
let shopName = this.state.shop_name;
let phonePrice = this.state.phone_price;
const phoneInfo = {'shop_name':shopName, 'phone_price':phonePrice};
this.setState((preState) => ({
avalilableShops: [...preState.avalilableShops, phoneInfo]
}), ()=>{ console.log(this.state.avalilableShops)});
}
render() {
const rows = this.state.avalilableShops.map((record,index) => {
return (
<tr key={index}>
<td>{record.shop_name}</td>
<td>{record.phone_price}</td>
<td>
<button
type="button"
className="btn btn-primary"
// onChange={this.createShops}
>
Delete
</button>
</td>
</tr>
);
});
return (
<div>
<label>Add shops that phone already available...</label>
<div className="row">
<div className="col-md-6">
<div className="form-group">
<select
name="shop_name"
className="form-control select2"
onChange={this.handleInputChange}
>
{this.state.shops.map((shops, index) => (
<option key={index} value={shops.name}>
{shops.name}
</option>
))}
;
</select>
</div>
</div>
<div className="col-md-4">
<div className="form-group">
<input
type="number"
name="phone_price"
placeholder="Price"
className="form-control"
value={this.state.phone_price}
onChange={this.handleInputChange}
/>
</div>
</div>
<div className="col-md-2">
<button
type="button"
className="btn btn-primary"
onClick={this.createShops.bind(this)}
>
Add
</button>
</div>
</div>
<br />
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Shop name</th>
<th scope="col">Price</th>
<th scope="col">Remove</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
</div>
);
}
}
我希望所有这些更改都发生在子组件中,因为在& createShop 方法中,我会使用传播运算符更新availableShops
。渲染组件很好。 availableShops
数组现在不会更新,但是我也想在父组件中使用它。请帮助我解决这个问题。
答案 0 :(得分:1)
不要将app.config['MONG_DBNAME'] = '<DB_name>'
app.config['MONGO_URI'] = 'mongodb+srv://<name>:<password>@<cluster_name>.net/<DB_name>?retryWrites=true'
存储到子组件的props
中
state
相反,您可以直接使用avalilableShops: this.props.avalilableShops,
来迭代并在子组件中显示数据,
props
对商店也是如此
const rows = this.props.avalilableShops.map((record,index) => { //access data using this.props
...
}
由于需要在父组件中访问数据,因此在父组件中应具有一个函数,该函数将更改父组件中的状态。将该功能传递给子组件,
在父组件中创建一个函数
{this.props.shops.map((shops, index) => ( //access shops using this.props
<option key={index} value={shops.name}>
{shops.name}
</option>
))}
将此功能传递给子组件
createShops = (phoneInfo) => {
this.setState({
avalilableShops: [...this.state.avalilableShops, phoneInfo]
}, ()=>{ console.log(this.state.avalilableShops)});
}
现在在子组件中,您需要调用父组件中的函数以更新状态,
<Child
shops = {this.state.shops}
onChange = {this.handleInputChange}
avalilableShops = {this.state.avalilableShops}
createShops = {this.createShops}
/>
答案 1 :(得分:1)
我已经更新了您的代码,并使其适用于您。
我在这里为您创建了演示
https://codesandbox.io/s/smoosh-night-33yn4
父组件
constructor(props) {
super(props);
this.state = {
availableShops: []
};
this.createShops = this.createShops.bind(this);
}
createShops(shop_name, phone_price) {
this.setState(preState => ({
availableShops: [...preState.availableShops, { shop_name, phone_price }]
}));
}
render() {
return (
<div>
<Child
createShops={this.createShops}
availableShops={this.state.availableShops}
/>
</div>
);
}
子组件
import React, { Component } from "react";
export default class Child extends Component {
constructor(props) {
super(props);
this.state = {
shop_name: "Shop 1",
phone_price: ""
};
this.shops = [{ name: "Shop 1" }, { name: "Shop 2" }, { name: "Shop 3" }];
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(e) {
const { name, value } = e.target;
this.setState({ [name]: value });
}
render() {
const rows =
this.props.availableShops &&
this.props.availableShops.map((record, index) => {
return (
<tr key={index}>
<td>{record.shop_name}</td>
<td>{record.phone_price}</td>
<td>
<button
type="button"
className="btn btn-primary"
// onChange={this.createShops}
>
Delete
</button>
</td>
</tr>
);
});
return (
<div>
<label>Add shops that phone already available...</label>
<div className="row">
<div className="col-md-6">
<div className="form-group">
<select
name="shop_name"
className="form-control select2"
onChange={this.handleInputChange}
>
{this.shops &&
this.shops.map((shops, index) => (
<option key={index} value={shops.name}>
{shops.name}
</option>
))}
;
</select>
</div>
</div>
<div className="col-md-4">
<div className="form-group">
<input
type="number"
name="phone_price"
placeholder="Price"
className="form-control"
value={this.state.phone_price}
onChange={this.handleInputChange}
/>
</div>
</div>
<div className="col-md-2">
<button
type="button"
className="btn btn-primary"
onClick={() => {
debugger;
const { shop_name, phone_price } = this.state;
this.props.createShops(shop_name, phone_price);
}}
>
Add
</button>
</div>
</div>
<br />
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Shop name</th>
<th scope="col">Price</th>
<th scope="col">Remove</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
</div>
);
}
}
输出
希望这对您有用!
答案 2 :(得分:0)
我将避免在父母和孩子中都保持avialableShops的状态。相反,我只会在您的父组件中维护availableShops的状态,可以通过将功能传递给子组件来对其进行更新。子组件可以通过父状态通过道具访问可用的商店,并且应在父状态/道具更新时重新呈现。这里是一个简化的解决方案:
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = { availableShops:[] }
}
handleUpdateShops = newShop => {
{ availableShops: oldShops } = this.state;
this.setState({ availableShops: [...oldShops, newShop] });
}
render{
return (
<div>
<Child
{...this.props}
{...this.state}
handleUpdateShops={this.handleUpdateShops}
/>
</div>
);
}
}
export default class Child extends Component {
constructor(props) {
super(props);
}
handleInputChange(e) {
...
}
createShops(e) {
e.preventDefault();
let shopName = this.state.shop_name;
let phonePrice = this.state.phone_price;
const phoneInfo = {'shop_name':shopName, 'phone_price':phonePrice};
this.props.handleUpdateShops(phoneInfo);
}
render() {
// this.props.availableShops available to map here
}
}