在不在父级中写入状态的情况下在反应中传递一个值

Passing a value up in react without writing state in parent

我想做什么: 我需要价格*数量=总数。我有一个 table,价格为 1,数量为 1,总计为 1。数量是一个计数器,需要有自己的状态,因为行将添加更多计数器。但我需要在父级 table 中使用该值,以便我可以使用它来计算总数。

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

//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>
  );
}

视觉参考:

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

// 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,尽管你通过了<Input prouct={...} />,我认为这是一个打字错误)