我怎样才能使它成为一个包含钩子的可调用实用程序函数?
How can I make this a callable utils function that contains a hook?
我目前正在使用 Apollo Client 的 useQuery
和 useMutation
挂钩在几个不同的组件中执行相同的功能。我不想重复逻辑,而是想创建一个可以将逻辑放在一个地方的辅助函数。
这个问题是,useQuery
和 useMutation
是钩子意味着它们不能作为函数存在于单独的文件中,而是需要是有效的 React 函数组件。
我开始尝试做一些功能性的东西,但开始认为这可能无法完成。
export function HandleFollow (props) {
const [useFollowUser, { followedData, followError }] = useMutation(FOLLOW_USER);
useFollowUser({ variables: { fromId: auth().currentUser.uid, toId: "userIDxyz"}, onCompleted: props.handleUserFollow(user, isFollowingAuthor)})
}
React Hooks 可以使用 util/helper 函数吗?提前致谢!
在创建以下内容时,我收到了 "Invalid hook call. Hooks can only be called inside of the body of a function component."
但我不明白为什么。
我认为这可能是由于从函数内部调用它造成的,但我不知道如何避免这种情况。
export function useHandleFollow(props) {
const { user, isFollowingUser } = props
const [useFollowUser, { followedData, followError }] = useMutation(FOLLOW_USER);
const [useUnfollowUser, { unfollowedData, unfollowedError }] = useMutation(UNFOLLOW_USER);
const [followSuccess, setFollowSuccess] = useState(false)
if(!isFollowingUser){
useFollowUser({ variables: { fromId: auth().currentUser.uid, toId: user.id}, onCompleted: setFollowSuccess(true)})
}else{
useUnfollowUser({ variables: { fromId: auth().currentUser.uid, toId: user.id}, onCompleted: setFollowSuccess(true)})
}
return followSuccess
}
当我立即在我的组件中调用它时(而不是从函数内部调用),它会继续无限地重新渲染:
下面是组件的一些更完整的代码
在Home.js中:
const followed = useHandleFollow({ user: author, isFollowingAuthor })
export default posts = (props) =>{
let { post, excludeUser = false } = props
let { author } = post
let { date, things, isFollowingAuthor } = post
let { profile_picture } = author
let currentUser = auth().currentUser
const [followed] = useHandleFollow({ user: author, isFollowingAuthor })
return ()
}
这是在 follow.js 中,我将其导入为 import { useHandleFollow } from...
export function useHandleFollow(props) {
const { user, isFollowingUser } = props
const [followUser, { followedData, followError }] = useMutation(FOLLOW_USER);
const [unfollowUser, { unfollowedData, unfollowedError }] = useMutation(UNFOLLOW_USER);
const [followSuccess, setFollowSuccess] = useState(false)
if(!isFollowingUser){
followUser({ variables: { fromId: auth().currentUser.uid, toId: user.id}, onCompleted: () => setFollowSuccess(true)})
}else{
unfollowUser({ variables: { fromId: auth().currentUser.uid, toId: user.id}, onCompleted: () => setFollowSuccess(true)})
}
return [followSuccess]
}
您可以创建一个 Custom Hook
来实现您的目标,方法是声明一个以 use
开头的函数,如下所示:
export function useHandleFollow (props) {
const [useFollowUser, { followedData, followError }] = useMutation(FOLLOW_USER);
useFollowUser({ variables: { fromId: auth().currentUser.uid, toId: "userIDxyz"}, onCompleted: props.handleUserFollow(user, isFollowingAuthor)})
}
请记住,所有 React Hooks Rule
也适用于 Custom Hooks
。
当然是!您可以创建自己的自定义反应挂钩。 React hooks 使用相当简单的命名约定,“use-”前缀。
export function useHandleFollow(props) {
const [useFollowUser, { followedData, followError }] = useMutation(
FOLLOW_USER
);
useFollowUser({
variables: { fromId: auth().currentUser.uid, toId: "userIDxyz" },
onCompleted: props.handleUserFollow(user, isFollowingAuthor)
});
}
Only Call Hooks from React Functions
Don’t call Hooks from regular JavaScript functions. Instead, you can:
- ✅ Call Hooks from React function components.
- ✅ Call Hooks from
custom Hooks (we’ll learn about them on the next page).
By following this rule, you ensure that all stateful logic in a
component is clearly visible from its source code.
下一页是 Extracting a Custom Hook 部分!
A custom Hook is a JavaScript function whose name starts with ”use”
and that may call other Hooks.
编辑
Still receiving invalid hook usage.
export function useHandleFollow(props) {
const { user, isFollowingUser } = props;
const [useFollowUser, { followedData, followError }] = useMutation(
FOLLOW_USER
);
const [useUnfollowUser, { unfollowedData, unfollowedError }] = useMutation(
UNFOLLOW_USER
);
const [followSuccess, setFollowSuccess] = useState(false);
if (!isFollowingUser) {
useFollowUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
} else {
useUnfollowUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
}
return followSuccess;
}
我认为这里的问题是“mutate”函数的命名,您给它命名很不方便,就像另一个 React Hook 一样。 React Hook linting 规则将 if (!isFollowingUser) {...}
解释为有条件地调用一个钩子,这是无效的。给他们一个非 React-hook 的名字。 useFollowUser
到 followUser
和 useUnfollowUser
到 unfollowUser
。
export function useHandleFollow(props) {
const { user, isFollowingUser } = props;
const [followUser, { followedData, followError }] = useMutation(
FOLLOW_USER
);
const [unfollowUser, { unfollowedData, unfollowedError }] = useMutation(
UNFOLLOW_USER
);
const [followSuccess, setFollowSuccess] = useState(false);
if (!isFollowingUser) {
followUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
} else {
unfollowUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
}
return followSuccess;
}
Still render looping
useHandleFollow
在每个渲染周期被调用。我认为您的自定义挂钩在无条件更新每个逻辑分支中的 followSuccess
状态时触发渲染循环。
export function useHandleFollow(props) {
...
const [followSuccess, setFollowSuccess] = useState(false);
// setFollowSuccess(true) called always
if (!isFollowingUser) {
followUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
} else {
unfollowUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
}
...
}
这最终更新状态 每次 调用钩子时。您应该在希望此效果为 运行 时设置条件,即将 that 代码块放在 useEffect
挂钩中,回调依赖于 [=23] =].效果回调仅在 isFollowingUser
值更改时才会 运行,而不是在组件呈现时。
export function useHandleFollow(props) {
const { user, isFollowingUser } = props;
const [followUser, { followedData, followError }] = useMutation(
FOLLOW_USER
);
const [unfollowUser, { unfollowedData, unfollowedError }] = useMutation(
UNFOLLOW_USER
);
const [followSuccess, setFollowSuccess] = useState(false);
useEffect(() => {
if (!isFollowingUser) {
followUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
} else {
unfollowUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
}
}, [isFollowingUser]);
return followSuccess;
}
Should I be returning something, like a set method or something, to
accept new props? Otherwise, how do I end up calling the hook with
those new props?
如果需要,您只需要 return 从钩子中获取更新程序功能。 React hooks 在每个渲染周期被调用,所以如果你将 props 传递给它们,那么它们将始终收到当前的 props。
我目前正在使用 Apollo Client 的 useQuery
和 useMutation
挂钩在几个不同的组件中执行相同的功能。我不想重复逻辑,而是想创建一个可以将逻辑放在一个地方的辅助函数。
这个问题是,useQuery
和 useMutation
是钩子意味着它们不能作为函数存在于单独的文件中,而是需要是有效的 React 函数组件。
我开始尝试做一些功能性的东西,但开始认为这可能无法完成。
export function HandleFollow (props) {
const [useFollowUser, { followedData, followError }] = useMutation(FOLLOW_USER);
useFollowUser({ variables: { fromId: auth().currentUser.uid, toId: "userIDxyz"}, onCompleted: props.handleUserFollow(user, isFollowingAuthor)})
}
React Hooks 可以使用 util/helper 函数吗?提前致谢!
在创建以下内容时,我收到了 "Invalid hook call. Hooks can only be called inside of the body of a function component."
但我不明白为什么。
我认为这可能是由于从函数内部调用它造成的,但我不知道如何避免这种情况。
export function useHandleFollow(props) {
const { user, isFollowingUser } = props
const [useFollowUser, { followedData, followError }] = useMutation(FOLLOW_USER);
const [useUnfollowUser, { unfollowedData, unfollowedError }] = useMutation(UNFOLLOW_USER);
const [followSuccess, setFollowSuccess] = useState(false)
if(!isFollowingUser){
useFollowUser({ variables: { fromId: auth().currentUser.uid, toId: user.id}, onCompleted: setFollowSuccess(true)})
}else{
useUnfollowUser({ variables: { fromId: auth().currentUser.uid, toId: user.id}, onCompleted: setFollowSuccess(true)})
}
return followSuccess
}
当我立即在我的组件中调用它时(而不是从函数内部调用),它会继续无限地重新渲染:
下面是组件的一些更完整的代码
在Home.js中:
const followed = useHandleFollow({ user: author, isFollowingAuthor })
export default posts = (props) =>{
let { post, excludeUser = false } = props
let { author } = post
let { date, things, isFollowingAuthor } = post
let { profile_picture } = author
let currentUser = auth().currentUser
const [followed] = useHandleFollow({ user: author, isFollowingAuthor })
return ()
}
这是在 follow.js 中,我将其导入为 import { useHandleFollow } from...
export function useHandleFollow(props) {
const { user, isFollowingUser } = props
const [followUser, { followedData, followError }] = useMutation(FOLLOW_USER);
const [unfollowUser, { unfollowedData, unfollowedError }] = useMutation(UNFOLLOW_USER);
const [followSuccess, setFollowSuccess] = useState(false)
if(!isFollowingUser){
followUser({ variables: { fromId: auth().currentUser.uid, toId: user.id}, onCompleted: () => setFollowSuccess(true)})
}else{
unfollowUser({ variables: { fromId: auth().currentUser.uid, toId: user.id}, onCompleted: () => setFollowSuccess(true)})
}
return [followSuccess]
}
您可以创建一个 Custom Hook
来实现您的目标,方法是声明一个以 use
开头的函数,如下所示:
export function useHandleFollow (props) {
const [useFollowUser, { followedData, followError }] = useMutation(FOLLOW_USER);
useFollowUser({ variables: { fromId: auth().currentUser.uid, toId: "userIDxyz"}, onCompleted: props.handleUserFollow(user, isFollowingAuthor)})
}
请记住,所有 React Hooks Rule
也适用于 Custom Hooks
。
当然是!您可以创建自己的自定义反应挂钩。 React hooks 使用相当简单的命名约定,“use-”前缀。
export function useHandleFollow(props) {
const [useFollowUser, { followedData, followError }] = useMutation(
FOLLOW_USER
);
useFollowUser({
variables: { fromId: auth().currentUser.uid, toId: "userIDxyz" },
onCompleted: props.handleUserFollow(user, isFollowingAuthor)
});
}
Only Call Hooks from React Functions
Don’t call Hooks from regular JavaScript functions. Instead, you can:
- ✅ Call Hooks from React function components.
- ✅ Call Hooks from custom Hooks (we’ll learn about them on the next page).
By following this rule, you ensure that all stateful logic in a component is clearly visible from its source code.
下一页是 Extracting a Custom Hook 部分!
A custom Hook is a JavaScript function whose name starts with ”use” and that may call other Hooks.
编辑
Still receiving invalid hook usage.
export function useHandleFollow(props) {
const { user, isFollowingUser } = props;
const [useFollowUser, { followedData, followError }] = useMutation(
FOLLOW_USER
);
const [useUnfollowUser, { unfollowedData, unfollowedError }] = useMutation(
UNFOLLOW_USER
);
const [followSuccess, setFollowSuccess] = useState(false);
if (!isFollowingUser) {
useFollowUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
} else {
useUnfollowUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
}
return followSuccess;
}
我认为这里的问题是“mutate”函数的命名,您给它命名很不方便,就像另一个 React Hook 一样。 React Hook linting 规则将 if (!isFollowingUser) {...}
解释为有条件地调用一个钩子,这是无效的。给他们一个非 React-hook 的名字。 useFollowUser
到 followUser
和 useUnfollowUser
到 unfollowUser
。
export function useHandleFollow(props) {
const { user, isFollowingUser } = props;
const [followUser, { followedData, followError }] = useMutation(
FOLLOW_USER
);
const [unfollowUser, { unfollowedData, unfollowedError }] = useMutation(
UNFOLLOW_USER
);
const [followSuccess, setFollowSuccess] = useState(false);
if (!isFollowingUser) {
followUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
} else {
unfollowUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
}
return followSuccess;
}
Still render looping
useHandleFollow
在每个渲染周期被调用。我认为您的自定义挂钩在无条件更新每个逻辑分支中的 followSuccess
状态时触发渲染循环。
export function useHandleFollow(props) {
...
const [followSuccess, setFollowSuccess] = useState(false);
// setFollowSuccess(true) called always
if (!isFollowingUser) {
followUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
} else {
unfollowUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
}
...
}
这最终更新状态 每次 调用钩子时。您应该在希望此效果为 运行 时设置条件,即将 that 代码块放在 useEffect
挂钩中,回调依赖于 [=23] =].效果回调仅在 isFollowingUser
值更改时才会 运行,而不是在组件呈现时。
export function useHandleFollow(props) {
const { user, isFollowingUser } = props;
const [followUser, { followedData, followError }] = useMutation(
FOLLOW_USER
);
const [unfollowUser, { unfollowedData, unfollowedError }] = useMutation(
UNFOLLOW_USER
);
const [followSuccess, setFollowSuccess] = useState(false);
useEffect(() => {
if (!isFollowingUser) {
followUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
} else {
unfollowUser({
variables: { fromId: auth().currentUser.uid, toId: user.id },
onCompleted: setFollowSuccess(true)
});
}
}, [isFollowingUser]);
return followSuccess;
}
Should I be returning something, like a set method or something, to accept new props? Otherwise, how do I end up calling the hook with those new props?
如果需要,您只需要 return 从钩子中获取更新程序功能。 React hooks 在每个渲染周期被调用,所以如果你将 props 传递给它们,那么它们将始终收到当前的 props。