React Native:在整个应用程序中使用全局变量的最佳实践是什么



我正在进行我的第一个React项目,我想使用某种全局变量,但我在理解React中变量的流和范围方面遇到了一些困难。

用户登录后,我将用户名保存在AsyncStorage中,这样下次他/她使用该应用程序时就会记住它。

const loginUser = (username, password) => {
// ... imaginary login fuctionality ...
this.saveUserName(username);
}
saveUserName  = async (username) => {
try {
await AsyncStorage.setItem("username",username);
} catch (error) {
console.log(error.message);
}
};

在身份验证成功并存储了用户名之后,我使用react导航来导航到HomeScreen。

saveUserName  = async (username) => {
try {
await AsyncStorage.setItem("username",username);
this.navigation.navigate("Home")
} catch (error) {
console.log(error.message);
}
};

所以我来到我的主屏幕,在那里我想显示一条包含用户名的欢迎信息。

return (
<View style={styles.loginContainer}>
<Text style={style.welcome}>Welcome [username should come here]</Text>
</View>
)

由于用户名在整个应用程序中保持不变,我想把它放在某种"全局"变量中,这样我就可以在整个应用过程中被检索到。我再次尝试在homescreen上从AsyncStorage检索它,但因为它是异步的,所以页面已经呈现。

由于我使用的是react导航,所以我可以从AsyncStorage中检索名称,并将其传递到导航函数中:

let username = await AsyncStorage.getItem("username");
this.props.navigation.navigate("Login", {
username: username,
});

这是可行的,但手动将此变量传递到我想要显示用户名的每个页面感觉是一种糟糕的做法。由于用户名没有更改,我想从AsyncStorage中多次检索它可能有些过头了?

有没有办法只从AsyncStorage检索一次所有值,然后将它们存储在某种全局变量中,以便在整个应用程序中使用它们?

我读过一些文章,说我可以将这些变量传递到我的应用程序的状态,但我似乎明白,这些变量只会从父母传递给孩子?我用一个功能组件制作了主屏幕,我知道它是无状态的,所以我想这不是一个选项吗?

提前感谢

用户登录后,我将用户名保存在AsyncStorage中,以便下次他/她使用应用程序时记住。

这与问题无关,但您需要在异步存储中保存一个令牌,使用该令牌可以获取用户对象,而不是在异步存储存储中存储用户名。如果你下次没有令牌,那么你就不能假设保存的用户名是有效的,并且用户已经登录。这是一个巨大的安全问题。

由于用户名在整个应用程序中保持不变

这不是真的,因为用户可以注销,使用户名无效,并使用不同的用户名登录。

这是有效的,但手动将此变量传递到我想要显示用户名的每个页面感觉是一种糟糕的做法。由于用户名不会更改

用户名确实发生了更改,这使得在params中传递用户名变得更糟,因为如果将来更改,传递的用户名将变得过时。无论如何,用户数据等数据不属于参数:https://reactnavigation.org/docs/params#what-应该在params 中

是否有一种方法可以从AsyncStorage中检索所有值一次,然后将它们存储在某种全局变量中,以便在整个应用程序中使用它们?

从异步存储中检索后,需要将它们存储在状态中。由于您希望在整个应用程序中使用此状态,因此需要将状态提升到根组件。

假设您有一个函数组件,您可以使用React的useState钩子来存储状态:https://reactjs.org/docs/hooks-state.html

为了能够在所有子组件中使用此状态,您可以使用React上下文公开该状态:https://reactjs.org/docs/context.html

function App() {
const [token, setToken] = React.useState({ checking: true });
React.useEffect(() => {
AsyncStorage.getItem('user_token').then(
(value) => setToken({ checking: false, value }),
(error) => setToken({ error })
);
}, []);
if (token.checking) {
return <LoadingScreen />;
}
return (
<UserTokenContext.Provider value={token.value}>
{/* rest of app code */}
</UserTokenContext.Provider>
);
}

如果您需要存储的不仅仅是令牌,您可能还需要使用全局状态管理库,如Redux或Mobx state Tree。

我似乎明白,变量只会从父传递到子

是的,道具总是从父级传递到子级。如果需要其他组件才能访问该状态,可以将其提升到父组件。

我用一个功能组件制作了主屏幕,我知道它是无状态

函数组件不是无状态的。它们可以使用useState钩子保持状态。尽管您的数据需要在根组件中,而不是主屏幕中,因为您还需要其他屏幕访问这些数据。

您可以创建一个类似DataHandler.js的实用程序类,并在登录成功后保存用户

/DataHandler.js

let user = {};
export default {
setUser(user) {
user = user;
},
getUser() {
return user;
}
};

类似的用法

import DataHandler from "./DataHandler";
saveUserName  = async (username) => {
try {
......
DataHandler.setUser(username); // Save User
......
} catch (error) {
console.log(error.message);
}
};

最新更新