I have multiple pages and they all have useState of different types:
//Page 1 ...
const [ShoppingListKey, setShoppingListKey] = useState<keyof ShoppingList>();
//Page 2 ...
const [isTrue, setIsTrue] = useState<boolean>(false);
//Page 3 ...
const [String, setString] = useState<string>('');
So, I have a component, and what I want it to do, is to take the target state value from its parent, and set its parents' state to the targeted value:
interface ChildProps {
targetStateValue: keyof ShoppingList | boolean | string | undefined;
setStateFunc: Dispatch<React.SetStateAction<keyof ShoppingList | boolean | string | undefined>>
}
export const Child = ({targetStateValue, setStateFunc}: ChildProps) => {
<button OnClick={()=>{setStateFunc(targetStateValue);}}>BUTTON</button>
}
In ShoppingList Parent:
<Child
setStateFunc={setShoppingListKey} //ERROR
targetStateValue={something}
/>
The Error says: Type 'Dispatch<SetStateAction<keyof ShoppingList | undefined>>' is not assignable to type 'Dispatch<SetStateAction<string | boolean | undefined>>'
You can use a generic component. Such component would work over a variety of types rather than a single one.
You define a generic interface for your child props. And a generic component which uses that interface as the type for its props.
interface ChildProps<T> {
targetStateValue: T;
setStateFunc: Dispatch<React.SetStateAction<T>>;
}
export const Child = <T>({
targetStateValue,
setStateFunc,
}: ChildProps<T>) => {
return (
<button
onClick={() => {
setStateFunc(targetStateValue);
}}
>
BUTTON
</button>
);
};
Using the above, we can change T
on invocation/definition and based on that the the internal types of the componet will change.
For simplicity i created a simple interface for ShoppingList and also gave a prefilled value to the state variable ShoppingListKey
. The code looks like below:
interface ShoppingList {
onion: string;
tomato: string;
}
interface ChildProps<T> {
targetStateValue: T;
setStateFunc: Dispatch<React.SetStateAction<T>>;
}
export const Child = <T>({
targetStateValue,
setStateFunc,
}: ChildProps<T>) => {
return (
<button
onClick={() => {
setStateFunc(targetStateValue);
}}
>
BUTTON
</button>
);
};
function App() {
const [ShoppingListKey, setShoppingListKey] =
useState<keyof ShoppingList>("tomato");
//Page 2 ...
const [isTrue, setIsTrue] = useState<boolean>(false);
//Page 3 ...
const [String, setString] = useState<string>("");
console.log({ ShoppingListKey, isTrue, String });
return (
<div className="App">
<Child<keyof ShoppingList>
targetStateValue={"onion"}
setStateFunc={setShoppingListKey}
/>
<Child<boolean> targetStateValue={true} setStateFunc={setIsTrue} />
<Child<string> targetStateValue={"test"} setStateFunc={setString} />
</div>
);
}
CodeSandbox
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With