Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: conditional dependency on useEffect? Or how to prevent redundancy?

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

like image 807
GWorking Avatar asked Oct 16 '25 04:10

GWorking


1 Answers

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

like image 184
GWorking Avatar answered Oct 17 '25 16:10

GWorking



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!