React:对useEffect的条件依赖?或者如何防止冗余?
React: conditional dependency on useEffect? Or how to prevent redundancy?
如果我有一个 React hook
不需要总是与 auth
状态链接(作为 useEffect
依赖项,我如何有条件地 删除此依赖项,或任何其他方法来防止 冗余 从而避免创建第二个几乎相同的钩子?
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']
}
编辑:更详细地说,在此示例中,钩子 useExample
负责 "this" 身份验证,但这是多余的,因为它已经由组件 Content
然而,这个钩子用在其他地方,它确实必须考虑这个授权
问题是如果我只想不让挂钩链接到 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>
);
}
根据@ford04 的评论,我可以使用对 useEffect 的条件依赖
然而,它是以警告为代价的
** 在这个例子中,在没有被授予访问权限的情况下总是执行挂钩感觉不合逻辑,但它的唯一用途是表明 useEffect
中的条件依赖是可能的(我没有不知道)
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
如果我有一个 React hook
不需要总是与 auth
状态链接(作为 useEffect
依赖项,我如何有条件地 删除此依赖项,或任何其他方法来防止 冗余 从而避免创建第二个几乎相同的钩子?
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']
}
编辑:更详细地说,在此示例中,钩子 useExample
负责 "this" 身份验证,但这是多余的,因为它已经由组件 Content
然而,这个钩子用在其他地方,它确实必须考虑这个授权
问题是如果我只想不让挂钩链接到 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>
);
}
根据@ford04 的评论,我可以使用对 useEffect 的条件依赖
然而,它是以警告为代价的
** 在这个例子中,在没有被授予访问权限的情况下总是执行挂钩感觉不合逻辑,但它的唯一用途是表明 useEffect
中的条件依赖是可能的(我没有不知道)
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