首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在道具更改时更新React/recompose组件?

如何在道具更改时更新React/recompose组件?
EN

Stack Overflow用户
提问于 2018-05-18 19:05:15
回答 2查看 1.7K关注 0票数 4

我正在编写这个产品列表组件,并且我正在与州政府作斗争。列表中的每个产品本身都是一个组件。除了组件在道具更改时不会更新之外,所有内容都是按照假设进行渲染的。我正在使用recompose的withPropsOnChange(),希望每次shouldMapOrKeys中的道具改变时都会触发它。然而,这种情况永远不会发生。

让我展示一些代码:

代码语言:javascript
复制
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)

我不认为这是相关的,但是addToCart函数返回一个Promise。现在,它总是解析为true

另一种解释是:currentProductssetProducts分别是保存购物车数据的类(模型)的属性和方法。这也很好用,没有抛出异常或显示出意外的行为。

这里的预期行为是:在将产品添加到购物车时和更新currentProducts列表之后,addedToCart属性将更改其值。我可以确认currentProducts正在按预期进行更新。然而,这是代码的一部分没有达到(我已经在该行添加了一个断点):

代码语言:javascript
复制
return Object.assign({
  addedToCart: currentProducts.indexOf(product.id) !== -1,
}, props)

由于我已经对另一个组件使用了类似的结构--主要区别是我“监听”的其中一个属性是由withState()定义的--所以我想知道我在这里遗漏了什么。我的第一个想法是这个问题是由currentProducts的直接更新引起的,这里:

代码语言:javascript
复制
currentProducts.push(product.id)

所以我尝试了一种不同的方法:

代码语言:javascript
复制
const products = [ product.id ].concat(currentProducts)
setProducts(products)

然而,在执行过程中,这并没有改变任何事情。

我正在考虑用withState代替withPropsOnChange。我想这是可行的。但在开始之前,我想知道我在这里做错了什么。

EN

回答 2

Stack Overflow用户

发布于 2018-05-18 20:46:18

正如我想象的那样,使用withState帮助我实现了预期的行为。然而,这绝对不是我想要的答案。不管怎么说,我还是把它贴在这里,希望能帮助其他遇到类似问题的人。我仍然希望找到一个答案来解释为什么我的第一个代码不能工作,尽管它没有抛出错误。

代码语言:javascript
复制
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. 删除了用于处理addedToCart;
  2. Started声明和创建设置器的addedToCart "calculation";
  3. Added withState,以便在产品成功添加到购物车时调用addToCart处理程序中的setAddedToCart(true)
  4. 通过重组的D17添加了componentWillReceiveProps事件,以便在道具更改时更新addedToCart

其中一些更新是基于this answer的。

票数 0
EN

Stack Overflow用户

发布于 2020-01-16 00:01:34

我认为您面临的问题是由于withPropsOnChange的返回值造成的。你只需要做:

代码语言:javascript
复制
withPropsOnChange([
    'product',
    'currentProducts',
  ], ({
      product,
      currentProducts,
    }) => ({
      addedToCart: currentProducts.indexOf(product.id) !== -1,
    })
)

withProps一样,withPropsOnChange会自动将你返回的对象合并成道具。不需要Object.assign()

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

附言:如果可以的话,我也会将条件替换为currentProducts.includes(product.id)。它更明确。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50409954

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档