复杂的React中的setState

huangapple go评论63阅读模式
英文:

Complex setState in React

问题

以下是您要翻译的部分:

我有一个包含订单列表的页面每个订单都有唯一的orderId页面上的每个订单部分都有两个文本框一个用于trackingID另一个用于carrierName我希望我的输入对象 - 使用setInput函数更新 - 能够记住所有已更新的订单

我编写了以下代码但如果我编辑属于不同orderId的文本框它会覆盖输入变量

const updateStatus = (e) => {
    const { id, value, name } = e.target;
  
    if (name === "trackingId") {
      setInput((prevState) => ({
        ...prevState,
        orderId: prevState.orderId || id,
        shipData: [{ ...prevState.shipData[0], trackingId: value }],
      }));
    } else if (name === "carrierName") {
      setInput((prevState) => ({
        ...prevState,
        orderId: prevState.orderId || id,
        shipData: [{ ...prevState.shipData[0], carrierName: value }],
      }));
    }
  
    console.log(`inputs are: ${JSON.stringify(input)}`);
};

以上代码在我编辑carrierName和trackingId文本框后生成以下对象:

{"orderId":"1","shipData":[{"carrierName":"carrierOne","trackingId":"TrackingOne"}]}

相反,如果我编辑第二个orderId的carrierName和trackingId文本框,我希望代码创建以下对象,即我希望状态保留先前的状态:

{"orderId":"1","shipData":[{"carrierName":"carrierOne","trackingId":"TrackingOne"}]},{"orderId":"2","shipData":[{"carrierName":"carrierTwo","trackingId":"TrackingTwo"}]}

出于某种原因,我无法使其正常工作,真的很感激那些比我聪明的人的帮助!


<details>
<summary>英文:</summary>

I have a page that contains a list of orders, each with a unique orderId. Each order section on the page has two text boxes, one for trackingID and one for carrierName. I would like my input object - that is updated using the setInput function - to &#39;remember&#39; all the orders that have been updated. 

I have written the following code, but it overwrites the input variable if I edit a text box belonging to a different orderId.

    const updateStatus = (e) =&gt; {
        const { id, value, name } = e.target;
      
        if (name === &quot;trackingId&quot;) {
          setInput((prevState) =&gt; ({
            ...prevState,
            orderId: prevState.orderId || id,
            shipData: [{ ...prevState.shipData[0], trackingId: value }],
          }));
        } else if (name === &quot;carrierName&quot;) {
          setInput((prevState) =&gt; ({
            ...prevState,
            orderId: prevState.orderId || id,
            shipData: [{ ...prevState.shipData[0], carrierName: value }],
          }));
        }
      
        console.log(`inputs are: ${JSON.stringify(input)}`);
      };

The code above produces the following object, after I edit carrierName and trackingId text boxes:

    {&quot;orderId&quot;:&quot;1&quot;,&quot;shipData&quot;:[{&quot;carrierName&quot;:&quot;carrierOne&quot;,&quot;trackingId&quot;:&quot;TrackingOne&quot;}]}

I would like the code to, instead, create this object, if I edit a second orderId&#39;s carrierName and trackingId text boxes, i.e., I want the state to keep the previous state:

    {&quot;orderId&quot;:&quot;1&quot;,&quot;shipData&quot;:[{&quot;carrierName&quot;:&quot;carrierOne&quot;,&quot;trackingId&quot;:&quot;TrackingOne&quot;}]},{&quot;orderId&quot;:&quot;2&quot;,&quot;shipData&quot;:[{&quot;carrierName&quot;:&quot;carrierTwo&quot;,&quot;trackingId&quot;:&quot;TrackingTwo&quot;}]}

For some reason, I just cannot make it work and I would really appreciate the help of someone who is cleverer than I am!

</details>


# 答案1
**得分**: 0

你在这两种情况下都在`setInput`中覆盖了你的输入 - 你要管理的状态只是一个对象,而不是你想要的数组。

那里的状态是:
```javascript
{
    orderId: number,
    shipData: Array<{ trackingValue: string, carrierName: string  }>
}

看起来你想要的输出是拥有一个像这样的状态:

Array<{
    orderId: number,
    shipData: Array<{ trackingValue: string, carrierName: string  }>
}>

让我快速为你准备一个解决方案 - 你可能想要在这里通过订单ID进行索引,而不是将它们存储在一个数组中。

编辑:

const App = () => {
  const [input, setInput] = React.useState({});

  const updateShipDataForOrder = (orderId, shipData) => {
      setInput((prevState) => {
          // 创建基于先前数据+新条目的新船数据
          const newShipData = {
              ...prevState[orderId],
              ...shipData,
          };

          // 在我们的状态中覆盖该值
          const newState = {
              ...prevState,
              [orderId]: newShipData
          };

          return newState;
      })
  }

  const updateStatus = (e) => {
      const { id, value, name } = e.target;

      updateShipDataForOrder(id, { [name]: value })
  };


  // 转换回你想要的数组
  const result = Object.entries(input).map(([orderId, shipData]) => {
      return {
          orderId,
          shipData
      }
  })

  return (
      <div>
        <div>
            <h1>Order one</h1>
            Tracking ID: <input id="1" name="trackingId" onChange={updateStatus} />
            Carrier Name: <input id="1" name="carrierName" onChange={updateStatus} />
        </div>
        <div>
            <h1>Order two</h1>
            Status: <input id="2" name="trackingId" onChange={updateStatus} />
            Carrier Name: <input id="2" name="carrierName" onChange={updateStatus} />
        </div>
        <br />
        <div>result: {JSON.stringify(result, null, '\t')}</div>
      </div>
  )
}

const root = document.getElementById('root')

ReactDOM.render(<App />, root)
英文:

You are overwriting your input with setInput here in both cases - the state you are managing is just an object rather than an array like you want.

The state there is:

{
orderId: number,
shipData: Array&lt;{ trackingValue: string, carrierName: string  }&gt;
}

It seems like the output you want is to have a state like

Array&lt;{
orderId: number,
shipData: Array&lt;{ trackingValue: string, carrierName: string  }&gt;
}&gt;

Let me whip up a quick solution - you probably want to index here by the orderId rather than storing these in an array.

Edit:

<!-- begin snippet: js hide: false console: true babel: true -->

<!-- language: lang-js -->

const App = () =&gt; {
const [input, setInput] = React.useState({});
const updateShipDataForOrder = (orderId, shipData) =&gt; {
setInput((prevState) =&gt; {
// Create new ship data based on the previous data + new entry
const newShipData = {
...prevState[orderId],
...shipData,
};
// Overwrite that value in our state
const newState = {
...prevState,
[orderId]: newShipData
};
return newState;
})
}
const updateStatus = (e) =&gt; {
const { id, value, name } = e.target;
updateShipDataForOrder(id, { [name]: value })
};
// Convert back to the array you wanted
const result = Object.entries(input).map(([orderId, shipData]) =&gt; {
return {
orderId,
shipData
}
})
return (
&lt;div&gt;
&lt;div&gt;
&lt;h1&gt;Order one&lt;/h1&gt;
Tracking ID: &lt;input id=&quot;1&quot; name=&quot;trackingId&quot; onChange={updateStatus} /&gt;
Carrier Name: &lt;input id=&quot;1&quot; name=&quot;carrierName&quot; onChange={updateStatus} /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h1&gt;Order two&lt;/h1&gt;
Status: &lt;input id=&quot;2&quot; name=&quot;trackingId&quot; onChange={updateStatus} /&gt;
Carrier Name: &lt;input id=&quot;2&quot; name=&quot;carrierName&quot; onChange={updateStatus} /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;result: {JSON.stringify(result, null, &#39;\t&#39;)}&lt;/div&gt;
&lt;/div&gt;
)
}
const root = document.getElementById(&#39;root&#39;)
ReactDOM.render(&lt;App /&gt;, root)

<!-- language: lang-html -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;root&quot;&gt;&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年7月20日 20:09:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76729698.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定