为什么子组件不更新?
Why isn't the child component updating?
当我更改产品名称时,在第一个案例中,我可以从 App -> List 跟踪更改。但是 list_item 没有更新它的道具。我认为问题是组件没有重新渲染,但确实如此。就是道具没有更新,不知道为什么。
app.js
import React, { Component } from 'react';
import List from './list';
class App extends Component {
constructor(props) {
super(props);
this.state = {
products: [
{
name: 'TV',
price: 1000,
currency: 'USD'
},
{
name: 'SSD',
price: 100,
currency: 'USD'
}
],
name: '',
price: '',
currency: ''
};
}
handleChange = event => {
console.log(`${event.target.name}: ${event.target.value}`);
this.setState({ [event.target.name]: event.target.value });
};
changeState = e => {
e.preventDefault();
let products = [...this.state.products];
products[0].name = this.state.name;
products[0].price = this.state.price;
products[0].currency = this.state.currency;
this.setState({
products
});
};
render() {
return (
<div>
<button onClick={() => console.log(this.state)}>log</button>
<List products={this.state.products} />
<p>{this.state.products[0].name}</p>
<form onSubmit={this.changeState}>
Name:
<br />
<input
type="text"
name="name"
// defaultValue={this.state.product.name}
onChange={this.handleChange}
/>
<br />
// for simplicity I'm skipping price and currency
// but they are there
<input type="submit" value="Update" />
</form>
</div>
);
}
}
export default App;
list.js
import React, { Component } from 'react';
import ListItem from './list_item';
class List extends Component {
constructor(props) {
super(props);
this.state = props;
}
render() {
const productItems = this.state.products.map((product, i) => {
console.log(product.name);
return (
<ListItem
key={i}
id={i}
name={product.name}
price={product.price}
currency={product.currency}
/>
);
});
return (
<table>
<tbody>
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
<th>Currency</th>
<th>Permissions</th>
</tr>
{productItems}
</tbody>
</table>
);
}
}
export default List;
list_item.js
import React, { Component } from 'react';
class ListItem extends Component {
constructor(props) {
super(props);
this.state = props;
}
render() {
console.log(this.state);
console.log('rendering');
return (
<tr>
<td>{this.state.id}</td>
<td>{this.state.name}</td>
<td>{this.state.price}</td>
<td>{this.state.currency}</td>
</tr>
);
}
}
export default ListItem;
您在 list_item.js
中遇到的问题是 this.state = props
在构造函数中。构造函数只被调用一次,所以状态是在你初始化组件时定义的,但从未更新过。
你真的不需要这个组件中的状态:
<tr>
<td>{this.props.id}</td>
<td>{this.props.name}</td>
<td>{this.props.price}</td>
<td>{this.props.currency}</td>
</tr>
并且因为您不需要状态,您可以使用无状态组件:
const ListItem = ({id, name, price, currency}) => (
<tr>
<td>{id}</td>
<td>{name}</td>
<td>{price}</td>
<td>{currency}</td>
</tr>
);
顺便说一下,您在 list.js
中也有同样的问题,这也可能是无状态组件。
如果你需要从 props 更新你的本地状态,你应该看看 getDerivedStateFromProps or 。
但在你的情况下,你不需要。
当我更改产品名称时,在第一个案例中,我可以从 App -> List 跟踪更改。但是 list_item 没有更新它的道具。我认为问题是组件没有重新渲染,但确实如此。就是道具没有更新,不知道为什么。
app.js
import React, { Component } from 'react';
import List from './list';
class App extends Component {
constructor(props) {
super(props);
this.state = {
products: [
{
name: 'TV',
price: 1000,
currency: 'USD'
},
{
name: 'SSD',
price: 100,
currency: 'USD'
}
],
name: '',
price: '',
currency: ''
};
}
handleChange = event => {
console.log(`${event.target.name}: ${event.target.value}`);
this.setState({ [event.target.name]: event.target.value });
};
changeState = e => {
e.preventDefault();
let products = [...this.state.products];
products[0].name = this.state.name;
products[0].price = this.state.price;
products[0].currency = this.state.currency;
this.setState({
products
});
};
render() {
return (
<div>
<button onClick={() => console.log(this.state)}>log</button>
<List products={this.state.products} />
<p>{this.state.products[0].name}</p>
<form onSubmit={this.changeState}>
Name:
<br />
<input
type="text"
name="name"
// defaultValue={this.state.product.name}
onChange={this.handleChange}
/>
<br />
// for simplicity I'm skipping price and currency
// but they are there
<input type="submit" value="Update" />
</form>
</div>
);
}
}
export default App;
list.js
import React, { Component } from 'react';
import ListItem from './list_item';
class List extends Component {
constructor(props) {
super(props);
this.state = props;
}
render() {
const productItems = this.state.products.map((product, i) => {
console.log(product.name);
return (
<ListItem
key={i}
id={i}
name={product.name}
price={product.price}
currency={product.currency}
/>
);
});
return (
<table>
<tbody>
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
<th>Currency</th>
<th>Permissions</th>
</tr>
{productItems}
</tbody>
</table>
);
}
}
export default List;
list_item.js
import React, { Component } from 'react';
class ListItem extends Component {
constructor(props) {
super(props);
this.state = props;
}
render() {
console.log(this.state);
console.log('rendering');
return (
<tr>
<td>{this.state.id}</td>
<td>{this.state.name}</td>
<td>{this.state.price}</td>
<td>{this.state.currency}</td>
</tr>
);
}
}
export default ListItem;
您在 list_item.js
中遇到的问题是 this.state = props
在构造函数中。构造函数只被调用一次,所以状态是在你初始化组件时定义的,但从未更新过。
你真的不需要这个组件中的状态:
<tr>
<td>{this.props.id}</td>
<td>{this.props.name}</td>
<td>{this.props.price}</td>
<td>{this.props.currency}</td>
</tr>
并且因为您不需要状态,您可以使用无状态组件:
const ListItem = ({id, name, price, currency}) => (
<tr>
<td>{id}</td>
<td>{name}</td>
<td>{price}</td>
<td>{currency}</td>
</tr>
);
顺便说一下,您在 list.js
中也有同样的问题,这也可能是无状态组件。
如果你需要从 props 更新你的本地状态,你应该看看 getDerivedStateFromProps or
但在你的情况下,你不需要。