Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何在道具更改时更新React/recompose组件?_Reactjs_Recompose - Fatal编程技术网

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

Reactjs 如何在道具更改时更新React/recompose组件?,reactjs,recompose,Reactjs,Recompose,我正在写这个产品列表组件,我正在与美国进行斗争。列表中的每个产品本身就是一个组件。所有内容都按预期进行渲染,但道具更改时组件不会更新。我正在使用recompose的with propsonChange()希望每次shouldMapworkeys中的道具更改时都会触发它。然而,这种情况从未发生过 让我展示一些代码: import React from 'react' import classNames from 'classnames' import { compose, withPropsOnC

我正在写这个产品列表组件,我正在与美国进行斗争。列表中的每个产品本身就是一个组件。所有内容都按预期进行渲染,但道具更改时组件不会更新。我正在使用recompose的
with propsonChange()
希望每次
shouldMapworkeys
中的道具更改时都会触发它。然而,这种情况从未发生过

让我展示一些代码:

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)
因为我已经为另一个组件使用了类似的结构——主要的区别是我正在“听”的一个道具是由
withState()
——定义的,我想知道我在这里缺少了什么。我的第一个想法是问题是由直接更新
currentProducts
引起的,这里:

currentProducts.push(product.id)
所以我尝试了一种不同的方法:

const products = [ product.id ].concat(currentProducts)
setProducts(products)
但在执行过程中,这并没有改变任何事情


我正在考虑使用带有state的
而不是带有propsonchange的
。我想那会有用的。但在这样做之前,我想知道我做错了什么。

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

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)
这里的变化是:

  • 删除了
    with propsonchange
    ,它用于处理
    addedToCart
    的“计算”
  • 添加了
    和state
    ,以声明和创建
    addedToCart
    的setter
  • 当产品成功添加到购物车时,开始在
    addToCart
    处理程序内调用
    setAddedToCart(true)
  • 通过重组的
    生命周期
    添加了
    组件将接收道具
    事件,以在道具更改时更新
    addedToCart

  • 其中一些更新是基于。

    我认为您面临的问题是由于
    withPropsOnChange的返回值造成的。您只需执行以下操作:

    withPropsOnChange([
    “产品”,
    “当前产品”,
    ], ({
    产品,,
    当前产品,
    }) => ({
    addedToCart:currentProducts.indexOf(product.id)!=-1,
    })
    )
    
    与使用
    withProps
    时一样,
    withPropsOnChange
    将自动将返回的对象合并到props中。不需要
    对象.assign()

    参考:


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

    听起来像是
    currentProducts
    发生了变异而不是更新。
    setProducts
    看起来像什么?它是这样的:
    @action setProducts=(products)=>{This.set('products',products)}
    。不确定这是否与任何wya相关,但
    setProducts
    所在的模型类用于其内部数据对象。@Oblosys请看下面我的答案。看来问题不在
    currentProducts
    上。但事实上,这并不能回答我最初的问题。我恐怕无法进一步帮助您,因为我觉得当
    currentProducts
    被修改而不是变异时,上面的代码应该可以工作。您可以尝试将函数作为第一个参数传递给
    withPropsOnChange
    ,以研究属性的确切变化。
    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)