我有一些父組件,如:
const ParentOne = () => {
const [error, setError] = useState<{ one: boolean }>({ one: false });
...omit
return (
<>
<Child setErr={setError} name={"one"} />
</>
);
};
const ParentTwo = () => {
const [error, setError] = useState<{ one: boolean; two: boolean }>({
one: false,
two: false,
});
...omit
return (
<>
<Child setErr={setError} name={"one"} />
<Child setErr={setError} name={"two"} />
</>
);
};
等等,不同數量的子組件和不同的
const[...] = useState<{ one: boolean; two: boolean; ...n: boolean }>({
one: false,
two: false,
...,
n: false
});
這是我的子組件:
const Child: FC<IChild> = ({ setErr, name }) => {
const handleClick = () => {
setErr((prev) => ({ ...prev, [name]: true }));
};
return <button onClick={handleClick}/>;
};
我不知道要為 setErr 設定哪種型別,因為 useState 對不同的父組件有不同的泛型。我試過這樣:
interface IChild {
setErr: React.Dispatch<React.SetStateAction<{ [key: string]: boolean }>>;
name: string;
}
但是在每個 Parent 組件中,setErr 要求 IChild 中的型別與 useState 中的泛型完全匹配
uj5u.com熱心網友回復:
所寫的setErr道具的真實型別Child是:
type ErrorSetter = React.Dispatch<React.SetStateAction<{[key: string]: boolean}>>;
我看到兩個選項:
用
Child書面和使用上的型別宣告setError(一對夫婦的方式之一,詳見下文)。使用自定義鉤子并簡化
Child
我更喜歡#2,但讓我們看看它們中的每一個:
采用Child書面型別的斷言
所以如果我們使用那個錯誤設定器,我們有:
type ErrorSetter = React.Dispatch<React.SetStateAction<{[key: string]: boolean}>>;
interface IChild {
setErr: ErrorSetter;
name: string;
}
如何在不不斷寫作的情況下使用它as?
很大程度上,我們不會,但您可能只為每個父組件執行一次:
const ParentTwo = () => {
const [error, setError] = useState({
one: false,
two: false,
});
const setErr = setError as ErrorSetter;
//
return (
<>
<Child setErr={setErr} name="one" />
<Child setErr={setErr} name="two" />
</>
);
};
這相當方便,并且Child保持不變,盡管通常(總是?)型別斷言的情況,它并不完全是型別安全的。
使用自定義鉤子
但我傾向于使用自定義鉤子并簡化Child. 鉤子是:
const useErrorState = <T,>(initial: T): [T, (name: keyof T) => void] => {
const [error, realSetError] = useState(initial);
const setError = useCallback(
(name: keyof T) => {
realSetError(prev => ({...prev, [name]: true}));
},
[]
);
return [error, setError];
};
如果您不需要setErr穩定,那么您可以像這樣使用它:
const ParentTwo = () => {
const [error, setError] = useErrorState({
one: false,
two: false,
});
//
return (
<>
<Child setErr={() => setError("one")} />
<Child setErr={() => setError("two")} />
</>
);
};
游樂場鏈接
...或者像這樣,如果你這樣做是因為你想避免Child重新渲染(這將假設Child使用React.memo或 [在類組件中]PureComponent或shouldComponentUpdate):
const ParentTwo = () => {
const [error, setError] = useErrorState({
one: false,
two: false,
});
const setErrorOne = useCallback(() => setError("one"), []);
const setErrorTwo = useCallback(() => setError("two"), []);
//
return (
<>
<Child setErr={setErrorOne} />
<Child setErr={setErrorTwo} />
</>
);
};
游樂場鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/377265.html
