If I have a React hook
that does not need always to be linked with the auth
state (as a useEffect
dependency, how can I conditionally remove this dependency, or any other way to prevent redundancy and thus avoid creating a second almost identical hook?
export const useHookAuth = () => {
// useless code
useEffect(() => {
if (!auth.user) return
// even uselesser code
}, [auth.user])
return ['with auth dependency']
}
export const useHookWithoutAuth = () => {
// the same useless code
useEffect(() => {
// identical even uselesser code
}, [])
return ['without auth dependency']
}
EDIT: more in detail, in this example the hook useExample
takes care of "this" auth, but this is redundant since it is already done before by the component Content
However, this hook is used elsewhere where it does have to take into account this auth
The question is how to avoid duplicating the hook if I only want not to have the hook linked to auth?
import React, { useEffect, useState, createContext, useContext } from "react";
import "./styles.css";
const AuthContext = createContext(null);
const useAuth = () => useContext(AuthContext);
const useAuthProvider = () => {
const [access, setAccess] = useState(0);
return { access, setAccess };
};
const useExample = () => {
const auth = useAuth();
const [content, setContent] = useState("");
useEffect(() => {
if (auth && !auth.access) return;
setContent("fetched content");
// even uselesser code
}, [auth]);
return [content];
};
const Button = () => {
const auth = useAuth();
return (
<button
onClick={() => {
auth.setAccess(1);
}}
>
clickme
</button>
);
};
const Content = () => {
const auth = useAuth();
const [content] = useExample();
return <h2>{(auth && auth.access && content) || "restricted"}</h2>;
};
export default function App() {
const authProvider = useAuthProvider();
return (
<AuthContext.Provider value={authProvider}>
<div className="App">
<h1>Hello CodeSandbox</h1>
<Button />
<Content />
</div>
</AuthContext.Provider>
);
}
https://codesandbox.io/s/tender-pike-ng4wg?file=/src/App.js
Based on @ford04 comments, I could use a conditional dependency on useEffect
It however goes at the cost of having a warning
** In this example it doesn't feel logical to execute always the hook without an access being granted, but its only use is to show that a conditional dependency in useEffect
is possible (which I didn't know)
import React, { useEffect, useState, createContext, useContext } from "react";
import "./styles.css";
const AuthContext = createContext(null);
const useAuth = () => useContext(AuthContext);
const useAuthProvider = () => {
const [access, setAccess] = useState(0);
return { access, setAccess };
};
const useExample = withoutAuth => {
const auth = useAuth();
const [content, setContent] = useState("");
useEffect(() => {
console.log(auth);
console.log(!withoutAuth);
if (auth && !auth.access && !withoutAuth) return;
setContent("fetched content");
console.log("done"); // this is executed always, regardless of auth
// even uselesser code
}, [withoutAuth ? null : auth]);
return [content];
};
const Button = () => {
const auth = useAuth();
return (
<button
onClick={() => {
auth.setAccess(1);
}}
>
Fetch
</button>
);
};
const Content = () => {
const auth = useAuth();
const [content] = useExample(1); // here I say NOT to implement auth
return <h2>{(auth && auth.access && content) || "restricted"}</h2>;
};
export default function App() {
const authProvider = useAuthProvider();
return (
<AuthContext.Provider value={authProvider}>
<div className="App">
<h1>Hello CodeSandbox</h1>
<Button />
<Content />
</div>
</AuthContext.Provider>
);
}
https://codesandbox.io/s/competent-currying-jcenj?file=/src/App.js
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