I want to change all the static text in my app with a text from a server so I have to fetch this text in LoadingScreen and then export it to use it in other screens
<Text>My products</Text> to <Text>{constants.myProduct}</Text> after import constant from LoadingScreen
How to export the json response from LoadingScreen to all the other Screen ?
there is another approach ?
PS. I don't use Redux
The simplest way, but not the best, is just create and export variable with all text keys. For example:
// text.utils.js
let _textData;
export const loadTextData = () => fetch(YOUR_SERVER)
.then((r) => r.json())
.then(r => _textData = r);
export const getTextData = (key, defaultValue) => _textData[key] || defaultValue;
// init inside App or something else
import {loadTextData} from 'text.utils.js';
componentDidMount() {
loadTextData();
}
// inside components
import {getTextData} from 'text.utils.js';
const myProductText = getTextData('myProduct', 'This is product text');
const myProductCountText = getTextData('myProductCount', 'This is product count text');
<Text>{myProductText}</Text>
<Text>{myProductCountText}</Text>
P.S. It's not a good solution for react. The best choice is create a context or hook, that will provide strings to your components. Also if your string object has nested objects, you may reorganise getTextData function
Related
Issue:
I am using react-intl and I would like to load the language-related JSON file only when it is needed, in brief to lazy load it.
Documentation :
https://reactjs.org/docs/code-splitting.html
the problem here is I wish to lazy load a JSON file not a component, so I am a bit lost about how to use it without JSX.
Actual code :
import React from 'react';
import {IntlProvider} from 'react-intl';
import English from "../i18n/en.json";
import Polish from "../i18n/pl.json";
const local = navigator.language;
let lang;
switch (local){
case "pl":
case "pl-pl":
lang = Polish;
break;
default:
lang = English;
}
function Wrapper () {
[...]
}
export default Wrapper
What I try which did not works :
test 1:
import React from 'react';
import {IntlProvider} from 'react-intl';
const English = React.lazy(() => import('../i18n/en.json'));
const Polish = React.lazy(() => import('../i18n/pl.json'));
const local = navigator.language;
let lang;
switch (local){
case "pl":
case "pl-pl":
lang = Polish;
break;
default:
lang = English;
}
function Wrapper () {
[...]
}
export default Wrapper
test 2:
import React from 'react';
import {IntlProvider} from 'react-intl';
const English = React.lazy(() => import('../i18n/en.json'));
const Polish = React.lazy(() => import('../i18n/pl.json'));
const local = navigator.language;
let lang;
switch (local){
case "pl":
case "pl-pl":
Polish.then(polish => {lang = polish});
break;
default:
English.then(english=> {lang = english});
}
function Wrapper () {
[...]
}
export default Wrapper
test 3 (inspired from How to import Json file with React lazy loading?) :
import React from 'react';
import {IntlProvider} from 'react-intl';
const local = navigator.language;
let lang;
switch (local){
case "pl":
case "pl-pl":
import("../i18n/pl.json").then(Polish=> {
lang = Polish);
});
break;
default:
import("../i18n/en.json").then(English=> {
lang = English);
});
}
function Wrapper () {
[...]
}
export default Wrapper
In case more code is needed (the function Wrapper for example), please let me know in a comment :)
I also had the same issue where I wanted to code split my JSON in React. I found a work around that uses the dynamic import function.
I wasn't using Intl so I can't confirm this works for your needs but this is what worked for my needs (and I think it should work for you)
I created a function to return a promise with my data that I needed to code split. I then called this in my Component in an Async func with an await on the data.
My use case was to fetch data from an API, if that was done, load a cached JSON of the data.
const loadCached = (key) => {
return new Promise((res, rej) => {
import(`../datasets/cached/${key}.json`).then((data) => {
res(data?.default);
});
});
};
I then called it from my async catch
const cachedData = await loadCached(key);
So for you use I would keep my loadCached function (maybe rename it to like loadLang)
then wrap it in a useEffect to fire on load to change the language and gather the JSON.
Here is how I would approach your issue (untested code)
const local = navigator.language; // get language
const [lang, setLang] = useState("English"); // for a default of english
// fire when we get local from DOM
useEffect(() => {
async function getLangData() {
const response = await loadLang(local);
setLang(reponse);
}
getLangData();
}, [local])
const setLang = (lang) => {
return new Promise((res, rej) => {
import(`../i18n/${lang}.json`).then((data) => {
res(data?.default);
});
});
};
I want to access json with a value in input.
My function and json
import pet3 from '../../utils/pet3' //my json file
const getValueFromJson = (value) => {
const data = pet3
console.log(data.components) //it works fine
console.log(data.value) // it is undefined
}
getValueFromJson("components")
You can access the object keys dynamically by using the square brackets:
import pet3 from "../../utils/pet3"; //my json file
const getValueFromJson = (value) => {
const data = pet3;
console.log(data[value]);
};
getValueFromJson("components");
Edit:
Alternately, you can install and use a 3rd party library like lodash which provides the _.get() method that can be used like this:
import get from "lodash/get"; // if not installed, run `npm install lodash --save-dev`
const getValueFromJson = (value) => {
const data = pet3;
console.log(get(data, value, "default value")); /* returns "default value" if key is undefined. */
};
getValueFromJson("components.filename");
I have a list of components coming from the server with JSON which is inside a variable.
I want to call the component dynamically.
listOfcomponents.map(x => {
<Route path={x.slug} component={x.component} />;//(SomeComponent)
});
this is the component
export const SomeComponent = (props) => {
return <div>Some Component</div>
}
The server is deciding about the component that will be called.
How do I let Route have a dynamic component?
Thanks
This is possible! What you're looking for is called: Dynamic imports. And it rocks!
I've had a similar case where I needed to render components dynamically. However the biggest challenge was to keep my routes organized. This is how I implemented this logic:
async function getComponent(route) {
const {default: module} = await import(`../${route}`)
const element = document.createElement('div')
element.innerHTML = module.render()
return element
}
I have a Vue component with lots of properties (> 40). It is a form for editing some business entity. The flow is the following:
On mounted() load the data as json from server and initialize component properties
Edit the data as required
Put all the properties into json structure and send back to server to update data
The properties in my component are named exactly the same as in json structure. I want to iterate through properties in my component and create json structure with 1 line of code instead of doing something like this:
var data = {
field1 = this.field1,
field2 = this.field2,
field3 = this.field3
...
field40 = this.field40
}
I use TS and vue-class-component, so the component code looks like this:
import Vue from 'vue'
import Component from 'vue-class-component'
#Component({
template: ...
})
export default class MyComponent extends Vue {
field1: Number = null;
field2: Date = null;
field3: String = null;
...
field40: Number = null;
mounted() {
axios.get(..., response => {
this.field1 = response.data.field1
this.field2 = response.data.field2
this.field3 = response.data.field3
...
this.field40 = response.data.field40
}
}
submit() {
const data = {
field1 = this.field1,
field2 = this.field2,
field3 = this.field3,
...
field40 = this.field40,
};
axios.put(..., data);
}
}
You could wrap your fields in a model field in your data:
data:{ model:{}}
Then on mounted you could set reactive props in your model
mounted(){
for(let field in YOUR_JSON_OBJ){
Vue.set(this.model, field , YOUR_JSON_OBJ[field])
}
}
Then when you need to submit form, just pass your vue model prop
YOUR_SUBMIT_METHOD(JSON.stringify(this.model))
I can see two ways to do this.
Provide a list of properties in an array, if you know it in advance (this is better practice as the data property gets initiated in the right way):
const props=['field1','field2', ...];
export default {
async mounted(){
//load the data and ensure only the expected properties are mounted
//this avoids any unexpected behaviour.
const result = await loadMyData();
for(let prop of props) this[prop]=result[prop];
}
data(){
//instantiate the data object to ensure all the properties are reactive
const data={};
for(let prop of props) data[prop]=null;
return data;
}
methods:{
async updateServer(){
//build the data object to send back to the server then send it.
const data={};
for(let prop of props) data[prop]=this[prop];
await sendUpdate(data);
}
}
}
The second way is to store a list of properties when you load the data from the server using Object.keys() and store this as a data property. You will then need to use vm.$set to ensure all of the properties have the correct reactivity, and you will not be able to have the properties at the root level, instead you will need to nest them (see the vue docs). However I assume that if your view object is designed to react to these properties then you must know them in advance.
Im setting my store on my react native app, is working fine with redux-dev-tools,
but I dont know how to refactor.
const store = createStore(reducer, /* preloadedState, */
composeEnhancers(
applyMiddleware(...middleware)));
const configureStore = () => {
return store;
};
export { configureStore };
The goal is to export only "store" as a function
Why do you want to export store as a function as you could just as well export it as an object?
export const store = configureStore();
This way you could also just import it in any file you like:
import { store } from '...';
// Now you can access the redux store and dispatch actions:
store.getState() ...
store.dispatch(...)