[英]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.