ホーム>source

OrderContentコンポーネントの小道具でいくつかの製品を取得して、selectコンポーネントで使用します。selectで製品を選択すると、SummaryコンポーネントとProductコンポーネントがレンダリングされます。これらのコンポーネントでは、数量を選択して、合計を計算できます。 OrderContentコンポーネントに戻ると、問題は入力タイプ(製品コンポーネント)でOnChangeを使用しようとすると、useEffect(状態の合計を計算する関数)がトリガーされませんが、製品を追加するとトリガーされます状態からまたはそれを削除します。

<前>ウィズウィズ import React, { Fragment, useState, useEffect } from "react"; import Select from "react-select"; import Animated from "react-select/lib/animated"; import Summary from './Summary'; function OrderContent({ products }) { const [productsSelected,setProductsSelected] = useState([]); const [total,setTotal] = useState(0); useEffect(() => { updateTotal() }, [productsSelected]); const selectProduct = (prod)=>{ setProductsSelected(prod) } const updateQuantity = (val,index)=>{ const tempProds = productsSelected; tempProds[index].quantity= Number(val); setProductsSelected(tempProds) } const deleteProduct = (id) =>{ const tempProds = productsSelected; const remProds = tempProds.filter((p)=> p.id !== id ); setProductsSelected(remProds); } const updateTotal = () =>{ const tempProds = productsSelected; if(tempProds.length === 0){ setTotal(0) return; } let newTotal = 0; tempProds.map((p)=>{ const q = p.quantity ? p.quantity : 0; newTotal = newTotal + (q * p.price) }) setTotal(newTotal) } return ( <Fragment> <h2 className="text-center mb-5">Select Products</h2> <Select onChange={selectProduct} options={products} isMulti={true} components={Animated()} placeholder={"Select products"} getOptionValue={options => options.id} getOptionLabel={options => options.name} value={productsSelected} /> <Summary products={productsSelected} updateQuantity={updateQuantity} deleteProduct = {deleteProduct} /> <p className="font-weight-bold float-right mt-3"> Total: <span className="font-weight-normal"> ${total} </span> </p> </Fragment> ); } export default OrderContent; import React, {Fragment} from 'react'; import Product from './Product'; function Summary({products,updateQuantity,deleteProduct}) { if(products.length === 0) return null; return ( <Fragment> <h2 className="text-center my-5">Summary and Quantities</h2> <table className="table"> <thead className="bg-success text-light"> <tr className="font-weight-bold"> <th>Product</th> <th>Price</th> <th>Inventory</th> <th>Quantity</th> <th>Delete</th> </tr> </thead> <tbody> {products.map((p,index)=>{ return (<Product key={p.id} id={p.id} product={p} index={index} updateQuantity={updateQuantity} deleteProduct={deleteProduct} />) })} </tbody> </table> </Fragment> ) } export default Summary import React, { Fragment } from "react"; function Product({ product, updateQuantity, index, deleteProduct }) { return ( <Fragment> <tr> <td>{product.name}</td> <td>${product.price}</td> <td>{product.stock}</td> <td> <input type="number" className="form-control" onChange={e => updateQuantity(e.target.value, index)} /> </td> <td> <button type="button" className="btn btn-danger font-weight-bold" onClick={e=> deleteProduct(product.id)}> &times; Delete </button> </td> </tr> </Fragment> ); } export default Product;
あなたの答え
  • 解決した方法 # 1

    ウィズウィズ  状態が変化しています。つまり、reactは、同じオブジェクト参照で状態を更新しようとしたことを確認し、再レンダリングはスキップされます。つまり、 updateQuantity はありません。  トリガー。

    これを次のように変更して、新しいネストされたオブジェクトで新しい配列を作成します。

    ウィズウィズ
    

    ウィズウィズ   useEffect が原因で変異しない  新しい配列を返します。しかし、 const updateQuantity = (val,index)=>{ const tempProds = [...productsSelected.map(val => {...val})]; tempProds[index].quantity= Number(val); setProductsSelected(tempProds) } の設定  完全に不要です。

    ウィズウィズ  状態も変化しますが、ネストされたオブジェクトのみが変化します。したがって、これはまだ修正する必要がありますが、おそらく同じ再レンダリングの問題は発生しません。

    deleteProduct の使用に基づく  いくつかの場所で、JavaScriptオブジェクトがどのように割り当てられ、参照されるかについていくつか調査する必要があると思います。たくさんのリソースがありますが、この回答の一部としてかなり詳細な説明を書きました。

  • 解決した方法 # 2

    productsSelectedが同じ配列の場合、useEffectは常に同じオブジェクトを指しているため、変更を検出できません。

    <前>ウィズウィズ

    選択した製品を強制的に新しいアレイにする

    filter

  • 前へ java - JPAクエリ:サブクエリをグループ化条件に結合する
  • 次へ ネストされた配列javascriptから二重引用符を削除する