前情回顧書接上回,前面引出了在數據存在級聯的狀況下,各下拉框之間的默認值及值變化的處理。簡單回顧一下:html 場景是:git
問題:github
解決:markdown
新的問題進一步實踐,會發現這種解決方式存在缺陷,在多級級聯的狀況下,好比三個下拉框 A->B->C,A 決定 B, B 決定 C,按照這個解決思路,優化
這顯然不科學,很是冗餘。同時從組件解耦的角度來看,A,B 須要知道誰依賴了本身從而重置它們,這種耦合很是難以維護。atom 所以應該反過來,將解決問題的邏輯囿於組件自身才是科學的作法。url 因而 A 無論其餘,只管本身隨便隨便怎麼變化,B 中監聽 A 變化而後作出反應以重置本身,C 監聽 B 的變化以重置本身。這樣邏輯作到了內聚無耦合。spa 而以前文章中之因此沒用這種方式,是由於發現該方式具備滯後性,組件內部會停留在錯誤的值上渲染一次。code export function ZoneSelect() {
+ const region = useRecoilValue(regionState);
const zones = useRecoilValue(zonesState);
const [zone, setZone] = useRecoilState(zoneState);
+ console.log("zone:", zone.id);
+ useEffect(() => {
+ setZone(zones[0]);
+ }, [region]);
return (
<label htmlFor="zoneId">
…
</label>
);
}
這裏會先打印一次舊值,等 狀態的正確使用細思會發現,上面之因此會有這種錯誤是由於姿式沒對,倘若咱們要使用可用區的值,應該在 useEffect(() => {
// do sth with zone
console.log("zone", zone.id);
}, [zone]);
此時打印就會獲得正確的結果。 按照這個邏輯修正後的組件及聯動關係就成了: RegionSelect.tsx export function RegionSelect() {
const regions = useRecoilValue(regionsState);
const [region, setRegion] = useRecoilState(regionState);
return (
<label htmlFor="regionId">
Region:
<select
name="regionId"
id="regionId"
value={region.id}
onChange={(event) => {
const regionId = event.target.value;
const region = regions.find((region) => region.id === regionId);
setRegion(region!);
}}
>
{regions.map((region) => (
<option key={region.id} value={region.id}>
{region.id}
</option>
))}
</select>
</label>
);
}
ZoneSelect.tsx export function ZoneSelect() {
const zones = useRecoilValue(zonesState);
const [zone, setZone] = useRecoilState(zoneState);
const resetZone = useResetRecoilState(zoneState);
const region = useRecoilValue(regionState);
// region 變化後重置 zone
useEffect(() => {
resetZone();
}, [region, resetZone]);
useEffect(() => {
// do sth with zone
console.log("zone", zone.id);
}, [zone]);
return (
<label htmlFor="zoneId">
Zone:
<select
name="zoneId"
id="zoneId"
value={zone.id}
onChange={(event) => {
const zoneId = event.target.value;
const zone = zones.find((zone) => zone.id === zoneId);
setZone(zone!);
}}
>
{zones.map((zone) => (
<option key={zone.id} value={zone.id}>
{zone.id}
</option>
))}
</select>
</label>
);
}
優化數據的依賴關係進一步思考,致使可用區須要重置的直接緣由其實並非地域發生了變化,而是地域發生變化後,可用區下拉框的可選項發生了變化,亦即 export function ZoneSelect() {
const zones = useRecoilValue(zonesState);
const [zone, setZone] = useRecoilState(zoneState);
const resetZone = useResetRecoilState(zoneState);
useEffect(() => {
resetZone();
}, [resetZone, zones]);
useEffect(() => {
// do sth with zone
console.log("zone", zone.id);
}, [zone]);
return (
<label htmlFor="zoneId">
Zone:
<select
name="zoneId"
id="zoneId"
value={zone.id}
onChange={(event) => {
const zoneId = event.target.value;
const zone = zones.find((zone) => zone.id === zoneId);
setZone(zone!);
}}
>
{zones.map((zone) => (
<option key={zone.id} value={zone.id}>
{zone.id}
</option>
))}
</select>
</label>
);
}
這樣一來,組件內部就清爽多了,只有自身相關的數據,甚至都去掉了對 |
The text was updated successfully, but these errors were encountered: |