如何在反应渲染中使用异步和等待

时间:2021-04-21 19:36:47

标签: reactjs react-native async-await

我正在开发一个 react-native 应用程序,我想要多语言支持。为了便于管理,我还编写了 languageHelper。

languageHelper.js

import AsyncStorage from '@react-native-async-storage/async-storage';

export const Translator = async (key) => {
    try {
        const langCode = await AsyncStorage.getItem('@lang_code')
        return I18n.t(key, { locale: langCode ?? 'en' })
    } catch (e) {
        return I18n.t(key)
    }
}

登录.js

render() {
        return (
            <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
                <KeyboardAvoidingView behavior={'height'} style={styles.container}>
                    <ScrollView>
                        <ImageBackground source={require('../Sources/LoginBg.jpg')} style={styles.backgroundImage}>
                            <Layout style={styles.header}>
                                <Text category='h1' status='primary'> {Translator('Login_hello')}</Text>
                                <Text category='h6' status='primary'> {Translator('Login_signInMessage')}</Text>
                            </Layout> 

我遇到的错误

Error: Objects are not valid as a React child (found: object with keys {_U, _V, _W, _X}). If you meant to render a collection of children, use an array instead.

但由于翻译器是一个异步函数,所以我不能在渲染中使用。 (我尝试异步渲染)。

我该如何解决这个问题?感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

好吧,这似乎是一个不太高效的代码,但是如果您无论如何都想让它工作,您可以在翻译工作时返回一个空字符串,如下所示:

import AsyncStorage from '@react-native-async-storage/async-storage';

export const Translator = React.memo(({key}) => {
    const [text, setText] = useState('')

    React.useEffect(() => {
       translate()
    }, [key])

    const translate = async () => {
        try {
           const langCode = await AsyncStorage.getItem('@lang_code')
           setText(I18n.t(key, { locale: langCode ?? 'en' }))
        } catch (e) {
           setText(I18n.t(key))
        }
    }
    
    return (
        <Text>{text}</Text>
    )
})

你可以在你的代码中像这样使用它(使用你的例子):

render() {
        return (
            <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
                <KeyboardAvoidingView behavior={'height'} style={styles.container}>
                    <ScrollView>
                        <ImageBackground source={require('../Sources/LoginBg.jpg')} style={styles.backgroundImage}>
                            <Layout style={styles.header}>
                                <Translator('Login_hello')} />
                                <Translator('Login_signInMessage')} />
                            </Layout> 

您还可以让译员接受样式道具以自定义最终结果。在那里使用 memo 也非常重要,这样您的翻译组件就不会有额外的渲染,因为它总是从异步请求。

其他解决方案

我实际推荐的解决方案是创建一个翻译提供程序并在那里全局配置 i18n,这样您将只有一个存储请求,并且您的翻译组件加载成本将真正降低。

您的项目取得成功。