I'm trying to use a hook in React. The hook should give me a boolean and a callback. When the callback gets called the boolean should change value. When I try to retrieve the value and the callback I get an error.
Property
isEnabled
does not exist on type(boolean | (() => void))[]
. On the lineconst {isEnabled, toggleCallback} = useToggle()
;
What am I doing wrong?
function toggleCallback(toggleCallback: () => void) {
toggleCallback();
}
export default function FakePage(props: any) {
const {isEnabled, toggleCallback} = useToggle();
return (
<div>
<ComponentOne isEnabled={isEnabled}/>
<button onClick={() => testToggle(toggleCallback)}>Test</button>
</div>
);
}
// hook
export default function useToggle() {
let isEnabled: boolean = true;
const toggleCallback= useCallback(() => {
isEnabled = !isEnabled;
}, [isEnabled]);
return [isEnabled, toggleCallback];
}
I'm trying to use a hook in React. The hook should give me a boolean and a callback. When the callback gets called the boolean should change value. When I try to retrieve the value and the callback I get an error.
Property
isEnabled
does not exist on type(boolean | (() => void))[]
. On the lineconst {isEnabled, toggleCallback} = useToggle()
;
What am I doing wrong?
function toggleCallback(toggleCallback: () => void) {
toggleCallback();
}
export default function FakePage(props: any) {
const {isEnabled, toggleCallback} = useToggle();
return (
<div>
<ComponentOne isEnabled={isEnabled}/>
<button onClick={() => testToggle(toggleCallback)}>Test</button>
</div>
);
}
// hook
export default function useToggle() {
let isEnabled: boolean = true;
const toggleCallback= useCallback(() => {
isEnabled = !isEnabled;
}, [isEnabled]);
return [isEnabled, toggleCallback];
}
Share
Improve this question
edited Jun 7, 2020 at 10:44
Dennis Vash
54.1k12 gold badges117 silver badges132 bronze badges
asked Jun 7, 2020 at 10:27
ZuenieZuenie
9732 gold badges13 silver badges32 bronze badges
2
- You are returning array from the hook but you destruct it as an object. either remove square brackets from callbacks and add curly brackets or change curly brackets in ponents to square brackets – Dilshan Commented Jun 7, 2020 at 10:31
- It is worth noting that you should use useState() for isEnabled inside your hook. Also, you probably don't need to useCallback because it will work the same for when isEnabled is true and false. – Deykun Commented Jun 7, 2020 at 10:34
2 Answers
Reset to default 4As for the error and types, currently you are returning a list which contains boolean
types and functions of type () => void
, where you want to return a tuple.
// Return from custom hook
return [isEnabled, toggleCallback];
// use it like so, and not as object { isEnabled,setIsEnbaled }
const [isEnabled,setIsEnbaled] = useToggle();
Fix the return types with:
return [isEnabled, toggleCallback] as const;
Or specify the return type:
type HookProps = (initialState: boolean) => [boolean, () => void];
const useToggle: HookProps = (initialState) => {...}
As for the hook implementation, it should look in JS like so, as variables are not connected to state, using toggleCallback
in your example won't trigger a render.
function useToggle(initialValue = true) {
const [isEnabled, toggle] = useReducer((p) => !p, true);
return [isEnabled, toggle];
}
how to create custom hook :
export default function FakePage(props: any) {
const {isEnabled, toggleCallback} = useToggle();
return (
<div>
<ComponentOne isEnabled={isEnabled}/>
<button onClick={toggleCallback}>Test</button>
</div>
);
}
// hook
export default function useToggle() {
const [isEnabled,setIsEnabled] = useState(true)
const toggleCallback= () => {
setIsEnabled(current=>!current);
};// no need to useCallback
return {isEnabled, toggleCallback};
}
// and if you want to pass default value
export default function useToggle(default) {
const [isEnabled,setIsEnabled] = useState(default)
const toggleCallback= () => {
setIsEnabled(current=>!current);
};// no need to useCallback
return {isEnabled, toggleCallback};
}
// usage
const {isEnabled, toggleCallback} = useToggle(false);