React Native 如何将这个组件重构为一个小组件?

dgsult0t  于 2022-11-17  发布在  React
关注(0)|答案(1)|浏览(113)

你建议如何重构下面的代码?这必须在应用程序的生命周期中运行一次。它有一个扩展代码和useEffect链接。
将resolveUser和syncDatabase函数作为操作添加到redux存储中是否是一种好的做法?

function App() {
    const {session, syncStatus} = getFromStore();

    const seedDatabase = useCallback(async () => {
        try {
            await seeder.seedProductsData();
            await seeder.seedDistributorData();
        } catch (error) {
            console.error('seeding failed');
        }
    }, []);

    const resolveUser = useCallback(async () => {
        try {
            let user;
            const userRes = await AsyncStorage.getItem('user');
            user = JSON.parse(userRes);
            if(user){
                user = await fetchUser(user);
                await AsyncStorage.setItem('user', JSON.stringify(user));
            }
            setSession(user); // Set Redux state
        } catch (error) {
            console.error('resolve user failed');
        }
    }, []);

    const syncDatabase = useCallback(async () => {
        try {
            setSyncStatus('started'); // Set Redux state
            await runSyncProcess();
            setSyncStatus('finished'); // Set Redux state
        } catch (error) {
            console.error('sync database failed');
            setSyncStatus('failed'); // Set Redux state
        }
    }, []);

    useEffect(() => {
        const resolveDatabase = async () => {
            if (db.isEmpty()){
                await seedDatabase();
            }
            await resolveUser();
            await syncDatabase();
        }
        resolveDatabase();
    }, []);

    useEffect(() => {
        if(session){
            syncDatabase();
        }
    }, [session]);

    ...

}
dced5bon

dced5bon1#

仅仅因为这里的长代码只在一个App组件中使用并不意味着它不能放在一个自定义钩子中。创建一个只在一个地方使用的自定义钩子是一个很好的模式,我喜欢遵循这个模式,否则原始组件会很混乱。对于你的代码,你可以这样做:

// should setSyncStatus, runSyncProcess, and others be passed down too?
const useDatabaseWithUser = ({ session, syncStatus }) => {
    const seedDatabase = useCallback(async () => {
        // ...
    }, []);
    
    // ...
    
    // other functions

    useEffect(() => {
        if(session){
            syncDatabase();
        }
    }, [session]);
};

然后App就可以摆脱所有这些功能:

function App() {
    const {session, syncStatus} = getFromStore();
    useDatabaseWithUser({ session, syncStatus });

如果useDatabaseWithUser太长,可以根据哪些函数的相关性最高,尝试将其拆分为更多的自定义钩子。看起来整个syncDatabase调用链可能不使用任何特定于React的东西,除了状态setter调用和用于函数定义的useCallback。如果是这种情况,可以将它们完全移出React并传递值。例如,在一个文件中:

export const resolveUser = ({ setSession }) => {
    try {
        const userDataJSON = await AsyncStorage.getItem('user');
        let user = JSON.parse(userRes);
        if (user){
            user = await fetchUser(user);
            await AsyncStorage.setItem('user', JSON.stringify(user));
        }
        setSession(user); // Set Redux state
    } catch (error) {
        console.error('resolve user failed');
    }
};

在调用程序中,导入resolveUser并将setSession作为参数传递。它需要一些样板来传递所有内容,但它允许您将代码拆分为任意多个单独的文件。

相关问题