If this is just adding BASE_URL, then this can be achieved by declaring it inside a constants.js file and exporting it from there. But then, that makes us do BASE_URL + "something" each time we make a network request which isn't really ideal either. Also there might be some scenarios where other configuration have to be shared, like say, a common header that has to be added to all the requests.
To solve this, most request libraries have in-build solutions. If we are choosing axios as the most popular one, we can create a instance like:
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
export default instance;
and import this everywhere the axios is going to be used like:
import axios from "./axios-instance";
assuming axios-instance.js is the file where the instance is created. Now you can skip adding the BASE_URL to every request as it is already provided in the instance.
If this is just adding BASE_URL, then this can be achieved by declaring it inside a constants.js file and exporting it from there. But then, that makes us do BASE_URL + "something" each time we make a network request which isn't really ideal either. Also there might be some scenarios where other configuration have to be shared, like say, a common header that has to be added to all the requests.
To solve this, most request libraries have in-build solutions. If we are choosing axios as the most popular one, we can create a instance like:
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
export default instance;
and import this everywhere the axios is going to be used like:
import axios from "./axios-instance";
assuming axios-instance.js is the file where the instance is created. Now you can skip adding the BASE_URL to every request as it is already provided in the instance.
If webpack is being used for code bundle, DefinePlugin can be used.
new webpack.DefinePlugin({
'BASE_URL': JSON.stringify('https://apiurlgoeshere.com/')
});
For gulp build, gulp-replace can be used.
.pipe(replace('BASE_URL', 'https://apiurlgoeshere.com/'))
How to use global variable in React js?
Global Variables in ReactJS - Stack Overflow
asynchronous - Use global variable to generate a dynamic url (React Native) - Stack Overflow
Define API url in a redux reactjs application - Stack Overflow
Global variables in React can be implemented using webpack.config.js file.
Inside the webpack config file declare your global variable.
i.e. const API_URL = JSON.stringify('http://api:8080'); Also, you need to add new plugins to webpack, in order for this global variable to be accessible by your whole app.
new webpack.DefinePlugin({ //defining gloabl variable
API_URL,
});
But global variable aside if just want to get rid of the component and module import error, then you can simply set aliases for those in your .babelrc file. This way, you do not need to write '../../..something', you can just write 'something'.
{
"presets": ["react", "es2015", "stage-0"],
"plugins": [
["module-resolver", {
"root": ["./src"],
"alias": {
"src": "/",
"components": "/components",
"actions": "/actions",
"containers": "/containers",
"images": "/images",
"reducers": "/reducers",
"styles": "/styles",
"utils": "/utils",
}
}]
]
}}
This is a sample .babelrc file with alias for components and other folders. Now from any where in the app if I write import { Something } from 'components/Something', my app will know where to find it. No need to write '../../../components/Something'
It is not recomended to use global variables, but you can simply use window object to save variables, for example window.myGlobalVar = 3. In addition, you can use react context.
Consider a simple API call using Axios:
Axios.get(`/api/v1/levels/${this.app.levelID}`)
.then(response => {
let data = response.data.data;
})
.catch(error => {
console.log(error)
});
I struggle to have properties of the data variable available outside the function processing the request. Data has properties such as data.name, data.gravity etc, which will be rendered when I call them within the function, but not anywhere else.
This API call is a part of a React component, and I would like to be able to access these values anywhere within the class after this call has been performed, of course.
I've tried using object properties this.name = data.name; this.gravity = data.gravity;, states: this.setState({name: data.name, gravity: data.gravity}), but nothing seemed to work. As soon as I left the function, though, whatever variable I appended these values to, they all returned undefined. That means that outside the function I would perform a call console.log(this.name) or like this this.state.name, but to no avail.
What am I doing wrong? How can I have data from API accessible as attributes throughout the entire class? Right now, I am using local storage, which is not very convenient and doesn't function properly.
Object properties work, as would most things, but they won’t be set until the request gets a response.
const request = Axios.get(...)
.then(response => {console.log(‘done!’); this.response = response});
console.log(`Response is ${this.response}`)
setTimeout(()=>console.log(`After 10s: the response is ${this.response}`, 10000)
Will likely show up as
Response is undefined
Done!
After 10s: the response is /*something*/
In the context of a react component, what you probably want is to run the query when the component mounts, and then store the output in the component state. The component re-renders when it’s state changes, so it’ll correctly update to hold the received data
class Level extends React.Component {
constructor(){
super();
this.state = {loading:true};
}
async componentDidMount(){
const request = await Axios.get(...):
const newState = { ...request, loading:false }
this.setState(newState);
}
render() {
if(this.state.loading){
return <p>loading...</p>
}
/*this.state has your stuff*/
}
const { data } = await Axios.get(`/api/v1/levels/${this.app.levelID}`);
this.setState({
data
})
const response = await fetch("http://127.0.0.1:5000/report"
What is the recommended way for me to store my apis? Should I store it in a .env file or a config file?Beyond React
You might not be aware that an import is global already. If you export an object (singleton) it is then globally accessible as an import statement and it can also be modified globally.
If you want to initialize something globally but ensure its only modified once, you can use this singleton approach that initially has modifiable properties but then you can use Object.freeze after its first use to ensure its immutable in your init scenario.
const myInitObject = {}
export default myInitObject
then in your init method referencing it:
import myInitObject from './myInitObject'
myInitObject.someProp = 'i am about to get cold'
Object.freeze(myInitObject)
The myInitObject will still be global as it can be referenced anywhere as an import but will remain frozen and throw if anyone attempts to modify it.
Example of react state using singleton
https://codesandbox.io/s/adoring-architecture-ru3vt (see UserContext.tsx)
If using react-create-app
(what I was looking for actually) In this scenario you can also initialize global objects cleanly when referencing environment variables.
Creating a .env file at the root of your project with prefixed REACT_APP_ variables inside does quite nicely. You can reference within your JS and JSX process.env.REACT_APP_SOME_VAR as you need AND it's immutable by design.
This avoids having to set window.myVar = %REACT_APP_MY_VAR% in HTML.
See more useful details about this from Facebook directly:
https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables
Why don't you try using Context?
You can declare a global context variable in any of the parent components and this variable will be accessible across the component tree by this.context.varname. You only have to specify childContextTypes and getChildContext in the parent component and thereafter you can use/modify this from any component by just specifying contextTypes in the child component.
However, please take a note of this as mentioned in docs:
Just as global variables are best avoided when writing clear code, you should avoid using context in most cases. In particular, think twice before using it to "save typing" and using it instead of passing explicit props.
It is a terrible idea, but probably the best/easiest way to use a global variable in React is to put it on the window. In a component you could do something like window.topicText="some text" and then access it via window.topicText everywhere else.
Ideally, if you have data, and in your case likely state, that you need to persist from component to component, you should look into something like Redux or Flux. I prefer Redux.
You can try this: Declare your global variable before your main component App.js and pass this variable as props down the tree.
Parent.js
var myVar = {}
class MyComponent extends Component {
...
...
myVar = new Object();
...
...
render() {
return <div>
\\ children
<MyLeftBranch myVar={myVar} />
<MyRightBranch myVar={myVar} />
</div>
}
}
export default MyComponent;
child.js
class Child extends Component {
{ myVar } = this.props;
\\use myVar
}