【问题标题】:Passing a value up in react without writing state in parent在反应中传递一个值而不在父级中写入状态
【发布时间】:2022-01-28 23:10:30
【问题描述】:

我正在尝试做的事情: 我需要价格 * 数量 = 总量。我有一张表,价格为一,数量为一,总数为一。数量是一个计数器,需要有自己的状态,因为行将添加更多的计数器。但我需要父表中的那个值,所以我可以用它来计算总数。

通常我会将计数器值放在父级中,但如果我这样做,当我更改一个计数器时,它们都会改变。那么我还能如何将值传递回父级呢?或者我在这里还有什么其他选择。

//parent
const memoData = useMemo(() => {
    return productList.map((product) => (
      <tr key={product.productNumber} className='productTable__row'>
        <td>
          <input
            placeholder='Product name'
            className='productTable__input productTable__input_product'
            defaultValue={product.productName}
          />
        </td>

        <td>
          <input
            placeholder='Id'
            className='productTable__input productTable__input_id'
            disabled
            defaultValue={product.productNumber}
          />
        </td>
        <td>
          <input
            placeholder='Price'
            className='productTable__input productTable__input_price'
            defaultValue={product.price}
          />
        </td>
        <td>
          <Input prouct={product} />
        </td>
        <td>
          <input
            placeholder='Total'
            className='productTable__input productTable__input_price'
            defaultValue={? * product.price}
          />
        </td>
        <td>
          <button
            className='productTable__btn_close'
            onClick={() => onProductDelete(product)}
          >
            <RiCloseFill fill='red' size='30px' />
          </button>
        </td>
      </tr>
    ));
  }, [onProductDelete, currentProduct, productList]);

//child
function Input() {
  const [counter, setCounter] = useState(1);

  const addOneClick = () => {
    setCounter(counter + 1);
  };

  const minusOneClick = () => {
    if (counter > 0) {
      setCounter(counter - 1);
    }
  };

  return (
    <div style={{ width: '88px' }}>
      <button
        className='productTable__btn_minus'
        style={{ borderRight: 'none' }}
        onClick={minusOneClick}
      >
        <FaMinus fill='var(--color-primary-blue)' size='14px' />
      </button>
      <input
        placeholder='0'
        className='productTable__input productTable__input_quantity'
        //   defaultValue={0}
        value={counter}
      />

      <button
        className='productTable__btn_plus'
        style={{ borderLeft: 'none' }}
        onClick={addOneClick}
      >
        <FaPlus fill='var(--color-primary-blue)' size='14px' />
      </button>
    </div>
  );
}

视觉参考:

【问题讨论】:

    标签: javascript reactjs jsx react-props react-usememo


    【解决方案1】:

    您应该将productList 视为父级中的“状态”,而不是counter,并且您应该将counter 作为product 的属性:

    // productList
    [
        {
            id: 123,
            counter: 0,           // <-- add a counter property
            productNumber: '...',
            // ...
        },
    ]
    
    // parent
    return productList.map( product => (
        <tr key={ product.productNumber } >
            <td>
                {/* add onSetCounter() callback */}
                <Input
                    product={ product }
                    onSetCounter={ id => { setCounter( id, count ); } }
                />
            </td>
        </tr>
    ));
    
    // child
    function Input() {
        const counter = props.product.counter;         // <-- use props
        const setCounter = props.setCounter;           // <-- use props
        // const [counter, setCounter] = useState(1);  // <-- don't use local state
    
        const addOneClick = () => {
            setCounter(counter + 1);
        };
    
        return (
            <button onClick={ addOneClick } >add one</button>
        );
    }
    
    // update the counter
    const setCounter = function( id, count ){
    
        // ... I don't know how you are managing your productList.
        // I would put this code into my redux-reducer. ...
    
        const newProductList = productList.reduce( (acc, product) => {
            if( product.id === id ){ // current product
                acc.push({
                    ...product,
                    counter: count
                })
            } else {                 // other products
                acc.push( product );
            };
        }, []);
    
    };
    

    (我在这里写了props.product,尽管你传递了&lt;Input prouct={...} /&gt;,但我认为这是一个打字错误)

    【讨论】:

    • 如果不由州管理,我对如何正确更新感到困惑
    • 我在回答中添加了更多细节
    猜你喜欢
    • 2017-03-24
    • 1970-01-01
    • 2020-06-22
    • 2020-10-05
    • 1970-01-01
    • 2015-04-23
    • 2017-04-04
    • 1970-01-01
    • 2019-11-16
    相关资源
    最近更新 更多