React Native - Invariant Violation - i18next integration - javascript

I am trying to create a react-native application, I'm currently at the starting point and I cannot understand an issue that I encountered.
I need to integrate i18next for translations. I did this by following their step-by-step tutorial
I have the following code
App.js
import React, { Suspense, Component } from 'react';
import { ScrollView, StyleSheet, Text, View, } from 'react-native';
import { useTranslation } from 'react-i18next';
import { Colors, } from 'react-native/Libraries/NewAppScreen';
const MyComponent = () => {
const { t, i18n } = useTranslation();
return <Text>{t('index.welcome')}</Text>;
};
const App = () => {
return (
<Suspense fallback="loading">
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={styles.scrollView}>
<View style={styles.body}>
<MyComponent />
</View>
</ScrollView>
</Suspense>
);
};
const styles = StyleSheet.create({
scrollView: {
backgroundColor: Colors.lighter,
},
body: {
backgroundColor: Colors.white,
},
});
export default App;
The issue here is that I get an Invariant Violation: Text strings must be rendered within a <Text> component error
If I change MyComponent to the following the application works
const MyComponent = () => {
return <Text>Anything</Text>;
};
So the issue here for me seems to be the useTranslation() hook.
What am I missing here?
LE
I was missing the namespace in the useTranslation()
I've added it useTranslations('translation') but still I have the same issue
The issue seems to be with the path for the translation files which cannot be parsed
i18next::backendConnector: loading namespace translation for language en failed failed parsing /translations/en/translation.json to json
In React the files would be public available via the public folder, in React-Native how should this be used? I think that the app cannot access that folder, where should the folder be placed?
LE2
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-xhr-backend';
i18n
.use(Backend)
.use(initReactI18next)
.init({
fallbackLng: 'en',
debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
backend: {
loadPath: '/translations/{{lng}}/{{ns}}.json',
},
});
export default i18n;
And the translations folder is placed in the root of the project

Related

React Native not picking functions from file directory

I am using react-native to build an app. The app has 2 screens: HomeScreen and Search screen. The file explorer cant find the module for Search but the same path for HomeScreen is working. Also I am using android if it helps.
My App.js includes:
import React from 'react';
import type { Node } from 'react';
import { StatusBar } from 'react-native';
import Search from './src/screens/Search/index';
const App: () => Node = () => {
return (
<>
<StatusBar barStyle='dark-content' />
<Search />
</>
);
};
export default App;
Search/index.js includes
import React from "react";
import { View, Text } from "react-native-vector-icons";
const Search = (props) => {
return (
<View>
<Text>Hi</Text>
</View>
);
};
export default Search;
Error:
However if I replace Search by HomeScreen, the app works. Could you please help my figure out what I am doing wrong. I am using the same code and same directory search style in both my index.js files. However, I made HomeScreen/index.js before Search/index.js.
Here is my HomeScreen/index.js
import React from "react";
import { View, Text } from "react-native";
import HomeMap from '../../components/HomeScreenMap';
const HomeScreen = (props) => {
return (
<View>
<HomeMap />
</View>
);
};
export default HomeScreen;
Here is my directory:
MEDLIFE
>__tests__
>.vscode
>android
>ios
>node_modules
>src
>components
>screens
>HomeScreen
>index.js
>Search
>index.js
.buckconfig
.editorconfig
.eslintrc.js
.flowconfig
.gitattributes
.gitignore
.prettierrc.js
.watchmanconfig
App.js
app.json
babel.config.js
index.js
metro.config.js
package.json
yarn.lock
Change this:
import { View, Text } from "react-native-vector-icons";
To this:
import { View, Text } from "react-native";

Why is react i18next not working ? no errors

The translations do not work I only see the keys. Instead of having "Welcome to MySite" I only have "welcome.title MySite".
my i18nextConf.js file
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-xhr-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
const fallbackLng = ['fr'];
const availableLanguages = ['en','fr'];
i18n
.use(Backend) // load translations using http (default public/assets/locals/en/translations)
.use(LanguageDetector) // detect user language
.use(initReactI18next) // pass the i18n instance to react-i18next.
.init({
fallbackLng, // fallback language is english.
backend: {
/* translation file path */
// loadPath: './translations/{{lng}}/{{ns}}.json'
loadPath: './translations/{{lng}}/common.json'
},
detection: {
checkWhitelist: true, // options for language detection
},
debug: false,
whitelist: availableLanguages,
interpolation: {
escapeValue: false, // no need for react. it escapes by default
},
});
export default i18n;
My index.js file
import React,{ Suspense } from 'react';
import './i18nextConf';
// code omitted
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<Suspense fallback={null}>
<App />
</Suspense>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
My translations files in src/translations/en/common.json and src/translations/fr/common.json
{
"welcome": {
"title": "Welcome to "
}
}
my CustomComponent.js
import React,{ Component } from 'react';
import { withTranslation } from "react-i18next";
class CustomComponent extends Component {
render() {
const { t } = this.props;
return (
<div className="section-title">
<h2 className={classes.myTitle}>{t('welcome.title')}</h2>
</div>
);
}
}
export default withTranslation()(CustomComponent);
Is there something wrong with my configuration ? What do I have to change ?
Those translation files will be served from the base path from where your index.html is also loaded and in-case it's an app created using create-react-app, that folder is public.
So I think when you are saying in loadPath that load files from ./translations/{{lng}}/common.json, the request actually gets resolved to public/translation/en/common.json but your files are located at src..... as you stated.
You can try either moving those files inside public (check this example for reference also ) or you can try the other syntax where you explicitly import the json from each file (inside src) and add it to a resources object which you pass to configuration as shown here

Element type is invalid React Native

I have been having this error for hours and I don't know how to fix it, it's driving me crazy. In this shortcode here, I keep getting this error:
Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: undefined. You
likely forgot to export your component from the file it's defined in,
or you might have mixed up default and named imports.
import * as Font from 'expo-font';
import React, {Component} from "react";
import { ActivityIndicator } from 'react-native'
import {Application} from "./src/Application.js";
class App extends Component {
constructor() {
super();
this.state = {
isReady: false,
};
}
componentWillMount = async() => {
await Font.loadAsync({
Roboto: require('./node_modules/native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('./node_modules/native-base/Fonts/Roboto_medium.ttf')
});
this.setState({isReady: true,});
};
render() {
if (!this.state.isReady) {
return <ActivityIndicator />
}
return (
<Application/>
);
}
}
export default App;
The error pointed to _callee$ in 18:16, which is this line
this.setState({isReady: true,});
What could be causing this and a possible solution?
I tried importing import {Application} from "./src/Application.js" without {} before, but it also returned the error of
Check the render method of _default
Edited: Added "Application.js"
import React from 'react';
import Root from "native-base";
import { createAppContainer } from '#react-navigation/native';
import { createStackNavigator } from 'react-navigation-stack';
import { createDrawerNavigator } from 'react-navigation-drawer';
import Home from "./screens/home/index";
import Email from "./screens/email/index";
import ProfileScreen from "./screens/ProfileScreen";
import SideBar from "./screens/SideBar/SideBar";
const Drawer = createDrawerNavigator(
{
Home: { screen: Home},
//Email: { screen: Email},
ProfileScreen: { screen: ProfileScreen}
},
{
initialRouteName: "Home",
contentOptions: {
activeTintColor: "#e91e63"
},
contentComponent: props => <SideBar {...props}/>
}
);
const AppNavigator = createStackNavigator (
{
Drawer: {screen: Drawer}
},
{
initialRouteName: "Drawer",
headerMode: "none"
}
);
const AppContainer = createAppContainer(AppNavigator);
export default () =>
<Root>
<AppContainer/>
</Root>
With this statement,
export default () =>
<Root>
<AppContainer/>
</Root>
Without parentheses,it will interpreted as
export default () =>();
<Root>
<AppContainer/>
</Root>
So,it will return undefined which is not valid react element.Because of this above error will occur.
wrap the export default statement with ().It should be
export default () =>(
<Root> <AppContainer/></Root>
);
OR
export default () =>( <Root> <AppContainer/></Root> );
And import should be
import Application from "./src/Application";
Try
import * as Application from './src/application.js';
You are not exporting a named item but just a function byt you are trying to import a named item.
Check that you are exporting Application correctly from Application.js.
It should just be "export Application".
You are probably importing your components the wrong way.
How are you exporting Application in Application.js ?
Maybe remove {} will fix it
import Application from "./src/Application.js";
There is two ways you can export/import
export function ...
// another file
import {...} from '...'
Or using the default export
export default function ...
// another file
import ... from '...'
If you want to import it like
import {Application} from "./src/Application.js";
You should be exporting it like
export function Application...
And if you look ate what the error says...
...You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

React Native: My (created) component isn't found?

I started a new project with react-native. I created a component called Home.jsx in app/components/home/. It looks like this:
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
} from 'react-native';
export default class Home extends Component {
render() {
return (
<View style={styles.container}>
<Text>This is the home component!</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default Home;
And my index.js (in the root) file looks like this:
import {AppRegistry} from 'react-native';
import Home from './app/components/home/Home';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => Home);
When I try to load up the app in the the emulator, I get this error message:
error: bundling failed: Error: Unable to resolve module
`./app/components/home/Home` from
`/Users/[my_name]/repos/[repo_name]/index.js`:
The module `./app/components/home/Home` could not be found from
`/Users/[my_name]/repos/[repo_name]/index.js`. Indeed, none of these
files exist:
What am I doing wrong?
I got it working by not using a folder called app and instead using src. I'm not entirely sure why this solved the issue but there we go!

Google+ Sign In with React Native, using Expo

I'm trying to implement a Sign In to Google from a React-native app. I found this question where someone give a way to do it, but is not working anymore or I'm doing something wrong.
My code is this one:
App.js
"use strict";
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { LoginGoogle } from './src/components/Login.js';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Open uuuup App.js ehh to start working on your app!</Text>
<LoginGoogle/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Login.js
"use strict";
import React, { Component } from 'react';
import Expo from 'expo';
import Button from 'react-native';
import { Text, View } from 'react-native';
class LoginGoogle extends Component {
signInWithGoogleAsync = async () => {
try {
const result = await Expo.Google.logInAsync({
androidClientId: process.env.GOOGLE_ANDROID_CLIENT_ID,
iosClientId: process.env.GOOGLE_IOS_CLIENT_ID,
scopes: ['profile'],
})
if (result.type === 'success') {
return result
}
return { cancelled: true }
} catch (e) {
return { error: e }
}
}
onLoginPress = async () => {
const result = await this.signInWithGoogleAsync()
// if there is no result.error or result.cancelled, the user is logged in
// do something with the result
}
render() {
return (<Button onPress={this.onLoginPress}>Login</Button>)
}
}
export default LoginGoogle;
When this is compiled, it says the following error:
Uncaught Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function but got: undefinded. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports
I already found when this error generally happen as states this other question. I already try importing LoginGoogle with and without curly braces, but without luck.
Any idea on what could be happening here? I know that if I put only a Text in LoginGoogle.js and import it from App.js works like a charm, so probably it has something to do with the functions that are related to Google Sign In, but it's a guess, I could be wrong.
You only need to change this line:
import { LoginGoogle } from './src/components/Login.js';
to
import LoginGoogle from './src/components/Login.js';
The first line would work if you exported Login like this:
export {LoginGoogle}
and not
export default LoginGoogle;

Categories