2017-08-02 147 views
0

我正在做简单的反应的应用程序。我需要下订单。对于该订单,我需要一份所有用户和产品的清单。我有CreateOrder组件,其state - usersproducts中有2个变量。这里是构造函数为什么React组件不渲染?

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.usersthis.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查看结果。这里是一张实际图片

enter image description here 正如你所看到的那样,有2个对象数组,每个对象都按照预期反应组件。

当我渲染CreateOrder我使用this.productsthis.users进行渲染,并且首先它们是空的。然后当商店中的东西发生变化时(它们充满了所有产品和用户)执行功能renderUsersrenderProducts,因此阵列中充满了数据。当发生这种情况时,我期望视图被更新。

现在的问题 - 当发生这种情况,并且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> 
    ) 
    } 
} 

回答

1

我不确定问题的实际原因,但我认为这与setState的异步行为有关,我们无法期望在setState后面更新状态值。

检查此answer有关setState的异步行为的更多详细信息。

解决方案:

存储在状态变量或在全局变量中的UI组件是不是一个好主意,所有的UI逻辑应该内呈现的方法,因此而不是存储在全局变量的选项,直接返回从那个功能。

无论何时我们做setState反应将重新渲染组件并用新数据更新ui。

第一步 -使用这些方法,去除另一个函数调用:

onProductChange(state) { 
    this.setState({products:state}) 
} 

onUserChange(state){ 
    this.setState({users:state}) 
} 

第二步 - 使用这些方法来呈现的选项:

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> 
    ) 
    ) 
} 

第三步 -调用这些函数从渲染到创建选项:

<select>{this.renderUsers()}</select> 
<select>{this.renderProducts()}</select> 
0

setState是异步的。尝试将您的this.renderUsers();置于componentWillUpdate生命周期方法中。

当接收到新的道具或状态时,立即调用componentWillUpdate()。使用此作为更新发生之前执行准备的机会。此方法不用于初始渲染。

您还可以使用的setState(updater, [callback])callback说法。