2017-08-02 234 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說法。