我正在制作简单的反应应用。我需要下订单。对于该订单,我需要一个包含所有用户和产品的列表。我的CreateOrder
组件在state
- users
和products
中有2个变量。这是构造函数
this.state.orders = OrderStore.getState()
this.state.products = ProductStore.getState()
this.state.users = UserStore.getState()
this.onOrderChange = this.onOrderChange.bind(this)
this.onProductChange = this.onProductChange.bind(this)
this.onUserChange = this.onUserChange.bind(this)
this.createOrder = this.createOrder.bind(this)
this.renderProducts = this.renderProducts.bind(this)
this.renderUsers = this.renderUsers.bind(this)
this.users = []
this.products = []
正如您所看到的,我正在使用3个商店,因此有3个功能来更新这些商店。之后,我有2个用于渲染产品和用户的功能。这些函数从其各自的变量中获取所有产品和用户,并创建一组option
标记以供使用<select>
。这些数组存储在this.users
和this.products
中,以便我可以使用它们。
以下是renderUsers
和renderProducts
renderUsers(){
this.users = this.state.users.users.map((user, i) => (
<option
key={i + 1}
value={user}>
{user.username}
</option>
)
)
console.log(this.users)
}
renderProducts(){
this.products = this.state.products.products.map((product, i) => (
<option
key={i + 1}
value={product}>
{product.name}
</option>
)
)
console.log(this.products)
}
我看不出两者之间有多大区别。制作阵列并填充option
个标签后,我使用console.log
查看结果。这是实际
当我呈现CreateOrder
时,我会使用this.products
和this.users
进行呈现,并且最初它们是空的。然后,当商店中的某些内容发生变化(它们充满了所有产品和用户)时,将执行函数renderUsers
和renderProducts
,因此数组将填充数据。发生这种情况时,我希望更新视图。
现在问题 - 当发生这种情况并且this.products
正在更新时,视图实际上会发生变化,并且实际上会更新所有产品的列表。但是 - 使用相同的逻辑和相同的功能和代码 - 用户不会被更新。他们保持不变。即使我将它们作为数组中的元素,我在render
中调用此数组,但它们并未更新。
在这里添加一些信息是我的整个CreateOrder
文件。
/**
* Created by PC on 01-Aug-17.
*/
import React from 'react'
import OrderActions from '../actions/OrderActions'
import ProductActions from '../actions/ProductActions'
import ProductStore from '../stores/ProductStore'
import UserActions from '../actions/UserActions'
import UserStore from '../stores/UserStore'
import OrderStore from '../stores/OrderStore'
import Select from './sub-components/SelectComponent'
import Input from './sub-components/InputComponent'
export default class CreateOrder extends React.Component {
constructor (props) {
super(props)
this.state = {}
this.state.orders = OrderStore.getState()
this.state.products = ProductStore.getState()
this.state.users = UserStore.getState()
this.onOrderChange = this.onOrderChange.bind(this)
this.onProductChange = this.onProductChange.bind(this)
this.onUserChange = this.onUserChange.bind(this)
this.createOrder = this.createOrder.bind(this)
this.renderProducts = this.renderProducts.bind(this)
this.renderUsers = this.renderUsers.bind(this)
this.users = []
this.products = []
}
componentDidMount () {
OrderStore.listen(this.onOrderChange)
ProductStore.listen(this.onProductChange)
UserStore.listen(this.onUserChange)
ProductActions.getAllProducts()
UserActions.getAllUsers()
}
componentWillUnmount () {
OrderStore.unlisten(this.onOrderChange)
UserStore.unlisten(this.onUserChange)
ProductStore.unlisten(this.onProductChange)
}
onOrderChange (state) {
this.setState({orders:state})
}
onProductChange(state) {
this.setState({products:state})
this.renderProducts()
}
onUserChange(state){
this.setState({users:state})
this.renderUsers()
}
createOrder (event) {
event.preventDefault()
let data = {}
data['username'] = this.state.orders.username
data['productName'] = this.state.orders.product.name
data['productPrice'] = this.state.orders.product.price
data['quantity'] = this.state.orders.quantity
OrderActions.addOrder(data)
}
renderUsers(){
this.users = this.state.users.users.map((user, i) => (
<option
key={i + 1}
value={user}>
{user.username}
</option>
)
)
console.log(this.users)
}
renderProducts(){
this.products = this.state.products.products.map((product, i) => (
<option
key={i + 1}
value={product}>
{product.name}
</option>
)
)
console.log(this.products)
}
render () {
return (
<div>
<div className='has-error'>
{this.state.orders.error}
</div>
<div className='has-success'>
{this.state.orders.success}
</div>
<form>
<select>{this.users}</select>
<select>{this.products}</select>
<div className="inputField">
<label htmlFor='title'>Quantity</label>
<Input
type='number'
name='price'
id='price'
placeholder='Price'
onChange={OrderActions.handleQuantityChange}
value={this.state.quantity}/>
</div>
<input type='submit' onClick={this.createOrder.bind(this)} value='Create Order'/>
</form>
</div>
)
}
}
答案 0 :(得分:1)
我不确定问题的实际原因,但我认为这与setState的异步行为有关,我们不能指望在setState之后更新的状态值。
检查此 answer ,了解有关setState的异步行为的更多详细信息。
<强>解决方案:强>
将ui组件存储在状态变量或全局变量中并不是一个好主意,所有ui逻辑都应该在render方法中,因此不是将选项存储在全局变量中,而是直接从该函数返回。
每当我们做setState
时,react会重新渲染组件并用新数据更新ui。
Step1 - 使用这些方法,删除了另一个调用函数:
onProductChange(state) {
this.setState({products:state})
}
onUserChange(state){
this.setState({users:state})
}
Step2 - 使用这些方法呈现选项:
renderUsers(){
if(!this.state.users.users) return null;
return this.state.users.users.map((user, i) => (
<option
key={i + 1}
value={user}>
{user.username}
</option>
)
)
}
renderProducts(){
if(!this.state.products.products) return null;
return this.state.products.products.map((product, i) => (
<option
key={i + 1}
value={product}>
{product.name}
</option>
)
)
}
第3步 - 从渲染中调用这些函数以创建选项:
<select>{this.renderUsers()}</select>
<select>{this.renderProducts()}</select>
答案 1 :(得分:0)
setState
是异步的。尝试将this.renderUsers();
放入componentWillUpdate
生命周期方法。
在呈现新的道具或状态时,会立即调用componentWillUpdate()。使用此作为在更新发生之前执行准备的机会。初始渲染不会调用此方法。
您还可以使用setState(updater, [callback])的callback
参数。