How can I use environment variables properly? - javascript

Im developing a white label app and I would like to know how can I use environment variables to generate specific color values and source images for different environments/builds.
Im using react-native-config to be able to manipulate/use env variables for my code specific builds.
//.env.fistapp
APP_BUILD=Environment-firstapp
LOGIN_LOGO_IMAGE=./images/1Logo.png
LOGIN_SOME_BOOL=true
LOGIN_BACKGROUND_COLOR=#333
LOGIN_SIMPLE_TEXT_COLOR=#FFF
LOGIN_TEXTINPUT_BACKGROUD_COLOR=#FFF
LOGIN_LOGIN_BUTTON_COLOR=#009933
For color values its working fine like this:
<View styles={background: ${Config.LOGIN_BACKGROUND_COLOR}}/>
For booleans I dont know the proper way to do it.. Env variables are always string so I guess the workaround is:
<Switch value={Config.LOGIN_SOME_BOOL === "true"}/>
But im having difficulties for source images. I get:
Invalid call at line 18: require(_reactNativeConfig.default.LOGIN_LOGO_IMAGE) at C:\Users\myuser\Desktop\myproject\whitelabel\node_modules\metro\src\JSTransformer\worker.js:318:19
I have tryed all this ways:
import Logo from Config.LOGIN_LOGO_IMAGE
import Logo from `${Config.LOGIN_LOGO_IMAGE}`
const Logo = Config.LOGIN_LOGO_IMAGE
<Image source={require(Config.LOGIN_LOGO_IMAGE)}/>
<Image source={{uri: require(Config.LOGIN_LOGO_IMAGE)}}/>

I think you need to put this string in quotes: LOGIN_LOGO_IMAGE="../../images/1Logo.png". As for the booleans, print out typeof(Config.LOGIN_SOME_BOOL) and if its a bool you need to do {Config.LOGIN_SOME_BOOL === true} (no quotes)

Related

Error : Text strings must be rendered within a <Text> component

I am making an app that you can make shopping list, ans want to make a voice input but it gives me the error: Text strings must be rendered within a component
{this.state.results.map((text, index) => {
return (
<Text key={index}>
Mensagem: {this.state.results}
</Text>
);
})}```
Make sure you’re bringing your built in components from react-native, not react-native-web.
Import {View, Text, ...} from "react-native"
I'm not familiar with react-native, but it sounds like the Text component expects a string, but got something else. this.state.results sounds like an array, is that correct? If you're trying to render something for each result you'll need to do something like:
return (
<div>
{this.state.results.map(result => (
<Text key={index}>
Mensagem: {result}
</Text>
))}
</div>
);
If each object in the results array is an actual object and not a string, you'll need to use a property like {result.name} or whatever is appropriate.
There is nothing wrong with the code you posted.
The problem is instead a letter, number or other character hiding somewhere in your JSX. This typicly happens when you accidently press a button without noticing.
This wont show as a warning in your IDE (example Visual Studio Code).
You can try and narrow down where the problem is by commenting out diffrent sections of you code and if you dont get an error you know you have found what code snippet the bad character is hiding in.
I even inserted your code into a react native project of mine just to confirm it works.
{["H", "E", "L", "L", "O"].map((text, index) => {
return (
<Text key={index}>
Mensagem: {text}
</Text>
);
})}
For everyone that is not that familiar with react native error messages or Text components.
Text components have no problem handling arrays as long as you dont insert objects into them. When you pass an object into a react native Text component you get this error: "Objects are not valid as a React child".

Isolating components from integrated app code in React

I'm looking for help isolating out components from my body of code. I can't figure out how to link the input and output variables that are currently integrated throughout the app code. I've tried pulling out short parts of rendered html(/jsx) and helper functions, but so far no luck. (this is a requirement for a training program.)
My approach has been to cut and paste the desired segment into a new javascript file, replace in the app function with a component call to the new js file (via exporting from component, importing in app), replace the object variable in the component with a simple abstract name (e.g., change "task" to "object") and establish equivilancies in the component call. However, I can't get this to work -- when I remove the original variables and replace with component calls, everything else stops recognizing their variables.
So I'm looking for advice and help on how to make components of the sections detailed below. Sorry if this is vague without the specific error messages and an entire detailing of my approaches so far -- I figure there is something I'm fundamentally missing about how to isolate components from the code I currently have -- All the information I've found that should be relevant relies on props to be attached to property variables in the app component, which is not how I have my app coded. I'm hoping I don't have to gut my code and start over.
To begin with, this is the smallest contained code, the basic content of the html:
//ListItem
<li
key={listItem.index}
onClick={() => {
handleClick(listItem.index);
}}
> {listItem.string}
</li>
after that would be its container element:
//Div
<div>
<h2>w/e</h2>
<ul>
{list
.map((item, index) => ({ ...item, index }))
.filter((item) => item.position === "right")
.map((listItem) => (
<ListItem props.../> // the ListItem component defined before
))}
</ul>
</div>
so that finally, i would have:
<body><Div props... /></body>
the last thing I'm trying to seperate as a component is an object array being used to set state via useState:
//Tasks
//const [list, setList] = useState(
[
{ string: "string", position: "position" } //and many more
]);
For each piece of the code that you extract, ask yourself "what information does this code need to render?" The answer to that question becomes your props. A ListItem needs key, onClick, and its contents. You can pass the contents as a string property, or you can make use of props.children.
Not every single JSX element needs to be its own component. Think about which chunks of code change depending on the variables of your app. Those variables become props and those code chunks become components.

Input value into react-native svg uri

Hello I am trying to input a value into an SVG URI in React-Native as follows:
source={require('../tasks/images/' + {task.image} + '.png')}
I am currently iterating through an array of objects and outputting the svgs for each, so I want to do it this way but the syntax isnt accepted.
Any help or advice is welcome!
Because there is no way to make the string passed to require dynamically, you could have an image collection file that references every image you would need, for example:
Create a file ImageCollection.js with the following:
export default imageCollection={
"1": require("./image1.png"),
"2": require("./image2.png"),
"3": require("./image3.png"),
"4": require("./image4.png")
}
Then import it into your file where you need to require your images and do something like this:
import Images from './ImageCollection.js';
class YourComponent extends Component {
renderItem = ({item}) => (
<View>
<Text>Image: {item}</Text>
<Image source={Images[item]}/>
</View>
);
render () {
const data = ["1","2","3","4","5"]
return (
<FlatList data={data} renderItem={this.renderItem}/>
)
}
}
export default YourComponent;
But if you really need to pass dynamic image sources then you could use a package like react-native-image-progress which lets you pass a variable as an image source, I wouldn't recommend this approach unless if there is absolutely no other way for you to solve this problem.
Here, you cannot pass dynamic images path which is available locally as your assests.
Moreover if you have image URI which is coming from the server then you can just provide here and it will work like a charm. But for image Path which is present locally you have to provide actual path. More you can read here.
However, what you can do just provide nested if else for the path based on the conditions, but then please note, you have to provide the full path as well.
Example :-
source={this.state.data===1?require('../tasks/images/image1.png'):this.state.data===2?require('../tasks/images/image2.png'):require('../tasks/images/image3.png')}
Thanks....Hope it helps :)

How to reuse SASS variable in JavaScript

I have list of color variables in JavaScript file as an Object.
export const colors = [
{
colorVariable: "$ui-background"
},
{
colorVariable: "$ui-01"
},
{
colorVariable: "$ui-02"
},
...
]
I created above object file based on scss file which have list of 50 colors. I used same name as scss variable So, i can use scss variable in my React component.
$carbon--theme: (
ui-background: #ffffff,
ui-01: #f3f3f3,
ui-02: #ffffff,
...
)
I imported those colors to jsx file from color.js file.
import { colors } from './theme';
And i want use that color variable to give background of following div. I tried following way So, i can apply scss variable. But, not working.
component.jsx
Code:
Object.keys(colors).map(key => {
return (
<div style={{ background: colors[key].colorVariable }} className={'theme-color')} />
)
})
I tried many things but nothing worked. Any help would be greatly appreciated. (It would be nice if i can use that variable in css (component.scss) file inside theme-color class. If not then ok ).
I am using react 16. Any help would be greatly appreciated and let me know if any questions.
First of all - the SASS variables does not exist on runtime. Are available only during compilation time.
The output CSS file does not include the SASS variables at all because and replaces any variable occurence with the raw value.
You might create CSS variables basing on the SCSS counterparts, then reuse the CSS variables in your code.
:root { /* or your element selector instead of `:root` so the variables will be scoped */
--ui-background: #{map-get($carbon--theme, "ui-background")};
--ui-01: #{map-get($carbon--theme, "ui-01")};
--ui-02: #{map-get($carbon--theme, "ui-02")};
}
Just create additional SASS/SCSS file with the snippet above.
Then simply adjust the values in the colors variable.
export const colors = [
{
colorVariable: "var(--ui-background)"
},
{
colorVariable: "var(--ui-01)"
},
{
colorVariable: "var(--ui-02)"
}
]
It perfectly works in runtime.
Bonus - if for some reason you need to reuse every color you might just iterate over the theme map using SASS's #each flow-control rule like:
:root { /* or your element selector */
#each $name, $color in $carbon--theme {
--#{$name}: #{$color};
}
}
BTW
The colors variable is an array so you don't need to get the keys in order to iterate over it.
There is an additional problem that probably throws an error:
className={'theme-color')} - you have a closing paren ) there.
Anyway, for the string values you can simply omit the JSX placeholders and pass the value directly in quotes.
Look at the fixed example:
colors.map(
(item) => <div key={item.colorVariable} style={{ background: item.colorVariable }} className="theme-color"/>
);
If the colors array consists only with the color values you might simply replace it with array of strings like:
['--ui01', '--ui02', ...]
Then it is even simpler:
colors.map(
(color) => <div key={color} style={{ background: color }} className="theme-color"/>
);
BTW #2.
If for some reason you don't want to use the CSS variables the other option is to use some library like scss-to-json that extracts the SCSS variables and outputs as JSON. This require an additional build step as well as importing/merging the JSON in your code base.

dynamic image for autocomplete / components

I am trying to make a crypto react native app, I am trying to have icons to match with an autocomplete. So it would work very similar to the coinmarketcap search, where you can type a coin symbol and you will see the corresponding coin with its icon.
I think there could be a few ways to do this and I think this would be a good place for discussion on what is the best way.
For starters, I created a script that would take all the icons in a directory (SVG or PNG), and create a json that would have the symbol as the value and the key will be a reference to the icon.
With this method there are a few problems I have encountered. The solutions have been covered in this post.
React Native - Dynamic Image Source.
However, it has been hard for me to find a good solution to either
A. Encode all the image in a directory into a base64encoded string and put it into a json
B. Create an array on the React Native end which will have the require('path-to-image')
Relevant code examples are in the post so i dont want to repeat it, but I guess I would just like to know which one is the best practice. I think that doing it as a array of modules would be best. But I am not sure have to dynamically create something like that.
example of the dictionary I created is something like this:
Given a JSON object like this how would you extend it so it would become
const image = {
key1: 'path/to/key/one.png'
key2: 'path/to/key/two.png'
}
To
{
key1: require('path/to/key/one.png'),
key2: require('path/to/key/two.png')
}
you would it to fit into a react native component like so
<Image
source={ (images[symbol])}
/>
You have a couple of options, and I think you nailed the best one in your case (tested in React Native 0.50.3):
import {Image} from 'react-native'
export default (props) => <Image source={icons[props.currency]} />
const icons = {
bitcoin: require('../path/to/bitcoin.png'),
ethereum: require('../path/to/ethereum.png'),
...
}
Lol that's basically exactly what you already wrote in your question. I've also gotten away with storing a bunch of require(...) statements in an array and pulled by index, e.g:
import {Image} from 'react-native'
export default (props) => <Image source={icons[props.index]} />
const icons = [
bitcoin: require('../path/to/bitcoin.png'),
ethereum: require('../path/to/ethereum.png'),
...
]
This approach is really only useful if you don't know the key to identify your target reference by (e.g if you wanted to cycle through a bunch of images randomly). For the described use case I'd go with key lookup.

Categories

Resources