首页 > 解决方案 > 如何使用 react 自定义钩子使代码可重用

问题描述

我有两个类似的组件,如下所示:

const Login = props => {
    let loading;
    const dispatch = useDispatch();
    const [notification, setNotification] = React.useState('');
    const [hasNotification, setHasNotification] = React.useState('');
    const [isLoading, setIsLoading] = React.useState(false);
    const {status, message} = useSelector(state => state.LoginReducer);
    const { register, handleSubmit, formState, errors } = useForm({
        mode: "onChange"
    });
    const onSubmit = data => {
        setIsLoading(true);
        dispatch(loginStart(data));
    };
    React.useEffect(() => {
        setIsLoading(false);
        if (status === 422) {
            setNotification(message);
            setHasNotification('ERROR');
            return;
        }
        if (status === 200) {
            setNotification(message);
            setHasNotification('SUCCESS');
        }
    }, [status, message]);
    React.useEffect(() => {
        console.log('componentDidMount');
        return () => {
            setNotification('');
            setHasNotification('');
        };
    }, []);
    return (
        <AuthLayout title={'Login'} header={'Welcome back, Sign in'} hasNotification={hasNotification} notification={notification}>
        </AuthLayout>
    )
}
export default Login;

我还有另一个与上述功能相似的组件

const Signup = props => {
    let loading;
    const dispatch = useDispatch();
    const [notification, setNotification] = React.useState('');
    const [hasNotification, setHasNotification] = React.useState('');
    const [isLoading, setIsLoading] = React.useState(false);
    const {status, message} = useSelector(state => state.SignupReducer);
    const { register, handleSubmit, formState, errors } = useForm({
        mode: "onChange"
    });
    const onSubmit = data => {
        setIsLoading(true);
        dispatch(signupStart(data));
    };
    React.useEffect(() => {
        setIsLoading(false);
        if (status === 422) {
            setNotification(message);
            setHasNotification('ERROR');
            return;
        }
        if (status === 200) {
            setNotification(message);
            setHasNotification('SUCCESS');
        }
    }, [status, message]);
    React.useEffect(() => {
        console.log('componentDidMount');
        return () => {
            setNotification('');
            setHasNotification('');
        };
    }, []);
    return (
        <AuthLayout title={'Signup'} header={'Discover a new way to do amazing work'} hasNotification={hasNotification} notification={notification}>
        </AuthLayout>
    )
}
export default Signup;

我阅读了自定义钩子,但只是好奇如何将状态和逻辑移动到单独的自定义钩子函数,因为它们具有相似的结构和功能。

自定义钩子会是什么样子?

标签: javascriptreactjsreact-hooks

解决方案


您可以在函数中声明所有状态/挂钩逻辑并将其导出到您的组件:

示例:对于您的登录组件,您可以将逻辑提取到文件中,我们称之为useLogin.js

useLogin.js

export default () => {
    const [notification, setNotification] = React.useState('');
    const [hasNotification, setHasNotification] = React.useState('');
    const [isLoading, setIsLoading] = React.useState(false);
    const { register, handleSubmit, formState, errors } = useForm({
        mode: "onChange"
    });
    React.useEffect(() => {
        setIsLoading(false);
        if (status === 422) {
            setNotification(message);
            setHasNotification('ERROR');
            return;
        }
        if (status === 200) {
            setNotification(message);
            setHasNotification('SUCCESS');
        }
    }, [status, message]);
    React.useEffect(() => {
        console.log('componentDidMount');
        return () => {
            setNotification('');
            setHasNotification('');
        };
    }, []);
   return [notification, hasNotification, setIsLoading]; //return all variable and functions that you need in your component
}

在登录中,您应该导入您的功能并使用它

import useLogin from './useLogin'; // first import useLogin function
const Login = props => {
    let loading;
    const dispatch = useDispatch();
    const {status, message} = useSelector(state => state.LoginReducer);
    const [notification, hasNotification, setIsLoading] = useLogin(); // call useLogin and get notification and hasNotification objects
    const onSubmit = data => {
        setIsLoading(true);
        dispatch(loginStart(data));
    };
    return (
        <AuthLayout title={'Login'} header={'Welcome back, Sign in'} hasNotification={hasNotification} notification={notification}>
        </AuthLayout>
    )
}
export default Login;

与注册组件相同

import useLogin from './useLogin';
const Signup = props => {
    let loading;
    const dispatch = useDispatch();
    const {status, message} = useSelector(state => state.SignupReducer);
    const [notification, hasNotification, setIsLoading] = useLogin();
    const onSubmit = data => {
        setIsLoading(true);
        dispatch(signupStart(data));
    };
    return (
        <AuthLayout title={'Signup'} header={'Discover a new way to do amazing work'} hasNotification={hasNotification} notification={notification}>
        </AuthLayout>
    )
}
export default Signup;

希望这个想法很清楚;


推荐阅读