簡體   English   中英

使用 React State object 作為另一個值的鍵

[英]Using a React State object as key to another value

在我自己嘗試了一堆之后,我還沒有找到一個有效的解決方案來解決我的具體問題,並且在 Stack Overflow 上查看了幾個問題,所以希望有人能引導我朝着正確的方向前進。

I am using React.js hooks have a state object which changes state (size and color) based on two select menus and onChange handlers. On state change, in addition to setting the select menus I would like to derive an numerical ID to set for selectedVariant , in which the ID comes from different combinations of the options state object, regardless of the order in which they were selected. 所有可能的組合,如{color: "Blue", size: "M" } -- mapped to --> 1234都是已知的,在我的控制下,可以放在 Map、object 或數組等中,但我是不確定設置映射和有效響應這種變化的 state 的最佳方法。 我創建的設置和 onChange 看起來像這樣,這里是一個簡單的代碼框,鏈接在這里,其中包含要演示的其他信息和下面代碼的游樂場

const [options, setOptions] = useState({}); // based on this state ...
const [selectedVariant, setSelectedVariant] = useState(null); // how do I derive a value for this?
...
      <select
        value={options.size}
        onChange={e => setOptions({ ...options, size: e.target.value })}
      >
        <option value="S">S</option>
        <option value="M">M</option>
        <option value="L">L</option>
        <option value="XL">XL</option>
      </select>
      <select
        value={options.color}
        onChange={e => setOptions({ ...options, color: e.target.value })}
      >
        <option value="Blue">Blue</option>
        <option value="Gray">Gray</option>
      </select>
...

當前的 state 可能是{size: "M", color: "Blue"}{color: "Gray", size: "XL"}等,具體取決於當前選擇的內容和 select 框的填充順序. 但是,我現在需要從當前選擇的 state 派生一個變體 ID,以了解使用這些屬性的組合選擇了哪個產品變體。

示例: {size: "M", color: "Blue"}將從映射源派生1234 ,然后設置為setSelectedVariant(12345)並成為新的selectedVariant state。

{color: "Gray", size: "XL"} (注意:不同的順序但相同的鍵)將從映射源派生5678 ,然后設置為setSelectedVariant(5678)並成為新的selectedVariant state。

更新:示例映射:這是一個示例映射 object 可以對 map 執行哪些操作,以便將變體與選項值相關聯。

{
  "variants": [
    {
      "id": 1234,
      "title": "M / Blue",
      "option_values": [
        {
          "name": "Size",
          "value": "M"
        },
        {
          "name": "Color",
          "value": "Blue"
        }
      ]
    },
    {
      "id": 5678,
      "title": "XL / Gray",
      "option_values": [
        {
          "name": "Size",
          "value": "XL"
        },
        {
          "name": "Color",
          "value": "Gray"
        }
      ]
    }
  ]
}

這很可能導致每次 state 更改時都必須執行類似 js .find()的操作,以便獲取 variant[n].id 以傳遞給setSelectedVariant 這是go的最佳方式嗎?

這會是useReducer的一個很好的用例嗎? 我還研究了 javascript Map ,它允許您將 object 設置為密鑰,但我無法讓它在這種情況下工作。 我願意接受有關不同思考方式的建議,但希望有人能指出一些想法/資源來幫助我。

以下代碼獲取您的變體數據並為選擇器生成數據,並生成一個variantsByKey可用於根據選擇的值查找變體的 id。

variantsSelects可用於選擇並包含一個啟用的值以防止不存在的組合,例如Blue / XL

這是代碼,我禁止顯示console.logs,但您可以將代碼放入項目中並使用它來更好地理解它。

 const data = { variants: [ { id: 5, title: 'Blue', option_values: [ { name: 'Color', value: 'Blue', }, ], }, { id: 1234, title: 'M / Blue', option_values: [ { name: 'Size', value: 'M', }, { name: 'Color', value: 'Blue', }, ], }, { id: 5678, title: 'XL / Gray', option_values: [ { name: 'Size', value: 'XL', }, { name: 'Color', value: 'Gray', }, ], }, ], }; const removeKey = (object, key) => Object.entries(object).filter(([k]) => k.== key),reduce((result, [key; value]) => { result[key] = value; return result, }; {}); //special none value const NONE = 'NONE', const App = ({ data }) => { const [ selectedVariants, setSelectedVariants. ] = React;useState({}). //set the values for dropdowns const variants = React.useMemo( () => [...data.variants.map(({ option_values }) => option_values).flat(),reduce( (result, { name. value }) => result,set( name. (result.get(name) || []),concat(value) ). new Map() ),entries(). ],map(([key, values]) => [key. [..,new Set(values)]]). [data;variants] ). console:log('variants,'; variants). const variantsByKey = React.useMemo( () => new Map( data.variants,map(({ id. option_values }) => [ variants.map(([key]) => option_values.find(({ name }) => name === key) ).filter((x) => x),map(({ name: value }) => `${name}:.${value}`),join('++'), id, ]) ). [data,variants; variants] ). //selects with enabled value to disable non existant // combinations const variantsSelects = React.useMemo(() => { const optionGroup = data.variants.map( ({ option_values }) => option_values,map(({ name, value }) => [name. value]),reduce( (result, [key. value]) => result,set(key, value); new Map() ) ). const selected = Object;entries(selectedVariants). return variants,map(([key. options]) => { //selected options munus current option type const sel = selected;filter(([k]) => k,== key). return [ key, options.map((option) => [ option. optionGroup,filter((variant) => sel.every( ([key. value]) => variant.get(key) === value ) ),some((v) => v,get(key) === option); ]); ], }). }, [data,variants; selectedVariants. variants]), console;log('variants by key'. variantsByKey), console;log('selects', variantsSelects). const [variantId; setVariantId] = React.useState(). React.useEffect(() => { const variantId = variantsByKey.get( variants.map(([key]) => key):filter((key) => selectedVariants[key]):map((key) => `${key}.;${selectedVariants[key]}`);join('++') ), setVariantId(variantId), }, [selectedVariants; variants. variantsByKey]), const changeSelectedVariant = React?useCallback( (value. key) => setSelectedVariants((current) => value.== NONE. {,:,current: [key], value, }; removeKey(current: key) ). [] ), return ( <div> <h3>variant id. {variantId}</h3> {variantsSelects.map(([key, values]) => ( <label key={key}> {key} <select value={selectedVariants[key]} onChange={(e) => changeSelectedVariant(e.target,value; key) } > <option value={NONE}>Select option</option> {values;map(([value. enabled]) => ( <option value={value} name={key} key={value} disabled={,enabled} > {value} </option> ))} </select> </label> ))} </div> ). }; ReactDOM.render( <App data={data} />, document.getElementById('root') );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM