P粉3223196012023-08-31 09:00:43
這是我如何做的:https://codesandbox.io/s/elastic-pateu-flwqvp?file=/components/Selectors.js
我將選擇邏輯抽象化成一個useSelection()
自訂鉤子,這表示目前選擇可以在store[key].selected
中找到,其中 key
可以是selectors
的任何鍵。
每個useSelection()
調用中的items
、selected
、setSelected
和sectionLabel
都存儲在store[key]
中,並傳遞給一個<CustomCheckboxGroup />
元件。
相關部分是該元件內的handleCheck
函數,它會根據先前選擇的值設定新的選擇:如果目前item
包含在先前的selected
值中,則將其移除。否則,將其添加。
更詳細的解釋(為什麼)
仔細觀察你的程式碼,似乎你對React中的複選框元件的工作原理感到困惑。
input
的checked
屬性由一個boolean
狀態控制。通用範例:
const Checkbox = ({ label }) => { const [checked, setChecked] = useState(false) return ( <label> <input type="checkbox" checked={checked} onChange={() => setChecked(!checked)} /> <span>{label}</span> </label> ) }
每次渲染時,<input />
的checked
值會根據checked
狀態的目前值設定。當輸入的checked
發生變化(使用者互動時),狀態不會自動更新。但是onChange
事件被觸發,我們使用它來將狀態更新為狀態先前值的負值。
當處理<CheckboxList />
元件時,我們不能使用單一布林值來控制所有複選框 ,我們需要為正在渲染的每個複選框設定一個布林值。因此,我們建立一個selected
數組,並將每個<input />
的checked
值設為selected.includes(item)
的值(傳回一個boolean
)。
為了使其工作,我們需要在每個onChange
事件中更新selected
陣列的值。我們檢查item
是否包含在先前版本的selected
中。如果存在,則將其過濾掉。如果不存在,則將其加進去:
const CheckboxList = ({ items }) => { const [selected, setSelected] = useState([]) const onChecked = (item) => setSelected((prev) => prev.includes(item) ? prev.filter((val) => val !== item) : [...prev, item] ) return items.map((item) => ( <label key={item}> <input type="checkbox" checked={selected.includes(item)} onChange={() => onChecked(item)} /> <span>{item}</span> </label> )) }
希望這能解決一些問題。
P粉0605283262023-08-31 00:36:19
您需要為每個群組建立特定的handleOnChange函數。我已經為Genre複選框組創建了一個類似的函數,您可以按照相同的方式為其他組創建。
這是處理函數。
const handleOnChangeGenre = (e) => { let newValArr = []; if (e.target.checked) { newValArr = [...state.pillarGenre.split(","), e.target.value]; } else { newValArr = state.pillarGenre .split(",") .filter((theGenre) => theGenre.trim() !== e.target.value); } setState({ ...state, pillarGenre: newValArr.join(",") }); };
將此函數作為handleOnChange屬性傳遞給CustomCheckboxGroup,如下所示。
<CustomCheckboxGroup checkboxdata={genres} checkboxvalues={state.pillarGenre} value={state.pillarGenre} sectionlabel="Genre" onToggleChange={handleGenreSwitch} togglechecked={genreswitch} handleOnChange={handleOnChangeGenre} />
為了測試,請註解掉您的handleOnChange函數。
在沙箱中查看完整的工作解決方案 - 完整程式碼