簡體   English   中英

更改 props 時如何更新 React/recompose 組件?

[英]How to get React/recompose component updated when props are changed?

我正在編寫這個產品列表組件,但我正在為狀態而苦苦掙扎。 列表中的每個產品本身都是一個組件。 一切都按預期渲染,除了在 prop 更改時組件不會更新。 我正在使用 recompose 的withPropsOnChange()希望每次更改shouldMapOrKeys的道具時shouldMapOrKeys觸發它。 然而,這永遠不會發生。

讓我展示一些代碼:

import React from 'react'
import classNames from 'classnames'
import { compose, withPropsOnChange, withHandlers } from 'recompose'
import { addToCart } from 'utils/cart'

const Product = (props) => {

  const {
    product,
    currentProducts,
    setProducts,
    addedToCart,
    addToCart,
  } = props

  const classes = classNames({
    addedToCart: addedToCart,
  })

  return (
    <div className={ classes }>
      { product.name }
      <span>$ { product.price }/yr</span>
      { addedToCart ?
        <strong>Added to cart</strong> :
        <a onClick={ addToCart }>Add to cart</a> }
    </div>
  )
}

export default compose(
  withPropsOnChange([
    'product',
    'currentProducts',
  ], (props) => {

    const {
      product,
      currentProducts,
    } = props

    return Object.assign({
      addedToCart: currentProducts.indexOf(product.id) !== -1,
    }, props)
  }),
  withHandlers({
    addToCart: ({
      product,
      setProducts,
      currentProducts,
      addedToCart,
    }) => {
      return () => {
        if (addedToCart) {
          return
        }
        addToCart(product.id).then((success) => {
          if (success) {
            currentProducts.push(product.id)
            setProducts(currentProducts)
          }
        })
      }
    },
  }),
)(Product)

我認為這addToCartaddToCart函數返回一個 Promise。 現在,它總是解析為true

另一個說明: currentProductssetProducts分別是一個屬性和一個方法,來自一個保存購物車數據的類(模型)。 這也很好用,不會拋出異常或顯示意外行為。

這里的預期行為是:將產品添加到購物車並更新currentProducts列表后, addedToCart道具將更改其值。 我可以確認currentProducts正在按預期更新。 但是,這是未到達代碼的一部分(我在該行中添加了一個斷點):

return Object.assign({
  addedToCart: currentProducts.indexOf(product.id) !== -1,
}, props)

由於我已經為另一個組件使用了類似的結構——主要區別在於我“聽”的一個道具是由withState()定義的——我想知道我在這里遺漏了什么. 我的第一個想法是問題是由currentProducts的直接更新引起的,這里:

currentProducts.push(product.id)

所以我嘗試了一種不同的方法:

const products = [ product.id ].concat(currentProducts)
setProducts(products)

不過,這在執行過程中沒有任何改變。

我正在考慮使用withState而不是withPropsOnChange 我想那會奏效。 但在采取這種方式之前,我想知道我在這里做錯了什么。

正如我想象的那樣,使用withState幫助我實現了預期的行為。 不過,這絕對不是我想要的答案。 無論如何,我在這里發布它願意幫助面臨類似問題的其他人。 我仍然希望找到一個答案來解釋為什么我的第一個代碼盡管沒有拋出任何錯誤但仍然不起作用。

export default compose(
  withState('addedToCart', 'setAddedToCart', false),
  withHandlers({
    addToCart: ({
      product,
      setProducts,
      currentProducts,
      addedToCart,
    }) => {
      return () => {
        if (addedToCart) {
          return
        }
        addToCart(product.id).then((success) => {
          if (success) {
            currentProducts.push(product.id)
            setProducts(currentProducts)
            setAddedToCart(true)
          }
        })
      }
    },
  }),
  lifecycle({
    componentWillReceiveProps(nextProps) {
      if (this.props.currentProducts !== nextProps.currentProducts ||
          this.props.product !== nextProps.product) {
        nextProps.setAddedToCart(nextProps.currentProducts.indexOf(nextProps.product.id) !== -1)
      }
    }
  }),
)(Product)

這里的變化是:

  1. 除去withPropsOnChange ,其用來處理addedToCart “計算”;
  2. 添加withState來為addedToCart聲明和創建一個 setter ;
  3. 當產品成功添加到購物setAddedToCart(true)開始調用addToCart處理程序中的setAddedToCart(true)
  4. 通過 recompose 的lifecycle添加componentWillReceiveProps事件以在道具更改時更新addedToCart

其中一些更新基於此答案

我認為您面臨的問題是由於withPropsOnChange的返回值。 你只需要做:

withPropsOnChange([
    'product',
    'currentProducts',
  ], ({
      product,
      currentProducts,
    }) => ({
      addedToCart: currentProducts.indexOf(product.id) !== -1,
    })
)

withPropswithPropsOnChange會自動將返回的對象合並到 props 中。 不需要Object.assign()

參考: https : //github.com/acdlite/recompose/blob/master/docs/API.md#withpropsonchange

ps:如果可以的話,我也會將條件替換為currentProducts.includes(product.id) 它更明確。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM