【问题标题】:On first launch choose language React Native首次启动时选择语言 React Native
【发布时间】:2021-01-13 23:49:42
【问题描述】:

我是新来的反应原生并使用I18n根据用户选择翻译我的多语言应用程序。

我的主要目标是在第一次进入应用程序时显示屏幕,该屏幕将根据用户的选择来决定用户语言。

import React from 'react';
import Login from './login.js';
import Register from './register.js';
import Dashboard from './dashboard.js';
import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { Text, View, Button } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';


const HAS_LAUNCHED = 'hasLaunched';
const ENGLISH = 'en';
const HEBREW = 'he';

function setAppLaunched(en) {
  const navigation = useNavigation();
  AsyncStorage.setItem(HAS_LAUNCHED, 'true');
  AsyncStorage.setItem(en ? ENGLISH : HEBREW, 'true');
  navigation.navigate('Login');
}

async function checkIfFirstLaunch() {
  try {
    const hasLaunched = await AsyncStorage.getItem(HAS_LAUNCHED);
    if (hasLaunched === null) {
      return (
        <View>
            <Text>Choose Language</Text>
            <Button onPress={() => setAppLaunched(false)} title="Hebrew"/>
            <Button onPress={() => setAppLaunched(true)} title="English"/>
        </View>
      );
    }
    return false;
  } catch (error) {
    return false;
  }
}

console.log(checkIfFirstLaunch());



const Stack = createStackNavigator();




export default function App() {
  
  return (
    <>
    <NavigationContainer>
      <Stack.Navigator screenOptions={{headerShown: false}} initialRouteName="Login">
        <Stack.Screen name="Login" component={Login} />
        <Stack.Screen name="Register" component={Register} />
        <Stack.Screen name="Dashboard" component={Dashboard} />
      </Stack.Navigator>
    </NavigationContainer>
    </>
  );
}

一旦checkIfFirstLaunch() 被触发,AsyncStorage 会保存用户语言并记住它,以备下次启动应用程序时使用。

我已经创建了检测用户是否首次启动应用程序的语法,但我如何才能真正显示该屏幕?

如何使用功能组件显示第一个启动屏幕?

编辑

export default function App() {
  
  return (
    <>
    <CheckIfFirstLaunch/>
    <NavigationContainer>
      <Stack.Navigator screenOptions={{headerShown: false}} initialRouteName="Login">
        <Stack.Screen name="Login" component={Login} />
        <Stack.Screen name="Register" component={Register} />
        <Stack.Screen name="Dashboard" component={Dashboard} />
      </Stack.Navigator>
    </NavigationContainer>
    </>
  );
}

如果我尝试它返回以下内容

错误:对象作为 React 子对象无效(找到:带键的对象 {_U、_V、_W、_X})。如果你打算渲染一组孩子, 改为使用数组。

【问题讨论】:

  • 但是您是想在每次启动时显示“选择”屏幕还是仅在用户未选择语言时显示?
  • @LuísMestre 仅在第一次发布时,但我似乎无法做到这一点,也许我应该使用 useEffect 钩子?

标签: javascript reactjs react-native


【解决方案1】:

错误是因为您正在渲染定义为异步函数的功能组件。

现在我不知道您是否想同时显示“选择”和导航屏幕。如果您愿意,请保持现有结构并执行此操作。

function checkIfFirstLaunch() {
  const [selected, setSelected] = useState(false);

  if (selected) return null;

  const verifyHasLaunched = async () => {
    try {
      const hasLaunched = await AsyncStorage.getItem(HAS_LAUNCHED);
      setSelected(hasLaunched != null)
    } catch (err) {
      setSelected(false);
    }
  }

  useEffect(verifyHasLaunched);

  const selectLaunched = (value) => {
    setAppLaunched(value);
    setSelected(true);
  };

  return (
    <View>
        <Text>Choose Language</Text>
        <Button onPress={() => selectLaunched(false)} title="Hebrew"/>
        <Button onPress={() => selectLaunched(true)} title="English"/>
    </View>
  );
}

如果您需要更改渲染,如渲染“选择屏幕”或导航组件

那么你必须同时改变 App 和 checkIfFirstLaunch;

function checkIfFirstLaunch({ onSelect }) {

  const selectLaunched = (value) => {
    setAppLaunched(value);
    onSelect();
  };

  return (
    <View>
        <Text>Choose Language</Text>
        <Button onPress={() => selectLaunched(false)} title="Hebrew"/>
        <Button onPress={() => selectLaunched(true)} title="English"/>
    </View>
  );
}

export default class App extends React.Component {
  state = {
    selected: false;
  };

  async componentDidMount() {
    try {
      const hasLaunched = await AsyncStorage.getItem(HAS_LAUNCHED);
      this.setState({ selected: hasLaunched != null })
    } catch (err) {
      // Something went wrong
    }
  }

  render() {

    if (!this.state.selected) return <CheckIfFirstLaunch onSelect={() => this.setState({ selected: true })} />

    return (
      <NavigationContainer>
        <Stack.Navigator screenOptions={{headerShown: false}} initialRouteName="Login">
          <Stack.Screen name="Login" component={Login} />
          <Stack.Screen name="Register" component={Register} />
          <Stack.Screen name="Dashboard" component={Dashboard} />
        </Stack.Navigator>
      </NavigationContainer>
    );
  }
}

【讨论】:

  • Error: Invalid hook call. Hooks can only be called inside of the body of a function component. - 单击其中一个选项后,我收到此错误
  • 是什么原因造成的?通过查看代码,钩子在App() 内。
  • 好吧,如果是这样的话,我将把 App 转换成一个类组件
  • @Yotam 我已经改变了答案,你必须从“react”导入 React
  • 有没有办法只使用功能组件来做到这一点?我试图避免在这个项目中上课
猜你喜欢
  • 2017-07-20
  • 1970-01-01
  • 2016-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多