I'm new to learning React, and I'm wondering why the following code doesn't work as expected. I thought that it would display The numbers: 0123
but it only displays 0
. I've also used the same approach with class based ponent, and using hooks and I still get the same result. What am I not understanding with react rendering using async code?
import React from "react";
import ReactDOM from "react-dom";
function App() {
let numbers = [0];
fetch("some.url")
.then(res => res.json())
.then(list => {
for (let n of list) {
numbers.push(n);
}
});
return <div className="App">The numbers: {numbers}</div>;
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
I'm new to learning React, and I'm wondering why the following code doesn't work as expected. I thought that it would display The numbers: 0123
but it only displays 0
. I've also used the same approach with class based ponent, and using hooks and I still get the same result. What am I not understanding with react rendering using async code?
import React from "react";
import ReactDOM from "react-dom";
function App() {
let numbers = [0];
fetch("some.url")
.then(res => res.json())
.then(list => {
for (let n of list) {
numbers.push(n);
}
});
return <div className="App">The numbers: {numbers}</div>;
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Share
Improve this question
edited Mar 13, 2019 at 13:06
Nini Michaels
asked Mar 13, 2019 at 13:02
Nini MichaelsNini Michaels
3397 silver badges19 bronze badges
3
- I've also made some code sandboxes to test it out: This is for the above example: codesandbox.io/s/nwlvnxxqkj This is the class approach: codesandbox.io/s/wqm2z43on7 And this is using hooks: codesandbox.io/s/43058qw614 – Nini Michaels Commented Mar 13, 2019 at 13:03
- 1 as @sjahan pointed out below, the state and the hooks examples didn't work because I was trying to load non secure json on a secure page. Updated to use https and now it works! – Nini Michaels Commented Mar 13, 2019 at 13:12
-
Side note, you can also return
null
while your request is loading, by checking ifnumbers === [0]
, something like this – Robin Métral Commented Mar 13, 2019 at 13:17
5 Answers
Reset to default 2Your code prints 0 because it is the value of the variable number
at render time.
You use the following code:
fetch("some.url")
.then(res => res.json())
.then(list => {
for (let n of list) {
numbers.push(n);
}
});
to get a new value asynchronously, but it won't have any effect: the ponent is already rendered.
If you want to refresh it, you must put your variable number in the state
and use setState()
to pass the new value.
If you want to keep with function ponents, you should use the brand new hooks feature, which should give you the equivalent of setState
.
You can use the useState
hook to create a piece of state that is an array, and get the list of numbers with the useEffect
hook and update the numbers when that request has finished.
Example
const { useState, useEffect } = React;
function getNumbers() {
return new Promise(resolve => {
setTimeout(() => {
resolve([1, 2, 3, 4, 5]);
}, 1000);
});
}
function App() {
const [numbers, setNumbers] = useState([0]);
useEffect(() => {
getNumbers().then(list => {
setNumbers(numbers => [...numbers, ...list]);
});
}, []);
return <div className="App">The numbers: {numbers.join(", ")}</div>;
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg./react@16/umd/react.development.js"></script>
<script src="https://unpkg./react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
The above code snippet would help you to understand the proper usage of dumb(aka Stateless) and smart(Stateful) ponent.
Start thinking of it using react life cycles, to make it even more clearer
In the above snippet the render() has already ran with the initial value
let numbers = [0];
and since the changes are not carried out in STATE or PROPS the rerendering is not happening and you are not getting the intended result.
Solution -
- Make the functional ponent a class ponent ie make it a smart ponent or use hooks (useState) to make it a smart ponent.
- Use prop drilling i.e calculate the value in the parent ponent and pass it down to the child ponent using props
Take this as an opportunity to prepare your mindset towards "THINKING in REACT"
More on Stateful vs Stateless
In frontend creation, rendering is the most important procedure a programmer has to handle. The render) (method in React is the only method needed in a class ponent and is responsible for defining the view to be rendered in the browser window. There are many subtleties about how this approach works, bined with the clever way that React operates around its virtual DOM concept, and knowing them would greatly benefit any aspiring React developer. For a demonstration of discussed habits, I will refer to this codepen. render() 101 Render) (is, first of all, not user-callable. It is part of the life cycle of the React ponent and is called by React at different phases of the app, normally when the React ponent is first instantiated, or when the ponent state is newly changed. Render does not take any arguments, and returns the JSX.Element that contains the current ponent's view hierarchy. This hierarchy of views will be later converted to HTML and shown in the browser window. Within the lifecycle, these are the scenarios where render is called:
After the React ponent is first instantiated, following the constructor() call. After an update to the ponent’s props After a setState() call I would remend this article- https://en.wikipedia/wiki/React_(web_framework) to understand the fundamentals, first.
That's a functional ponent, or a stateless
ponent. It has not it's own state. So if you change the value of the numbers variable, will not change the state of the ponent. If you really want to use a functional ponent, you should write the logic of fetching the url and updating the state in a parent stateful ponent and pass the numbers
variable as a prop to the stateless ponent.
Otherwise if you don't need to use a functional ponent. Change it to a class ponent, and put the numbers variable as a state parameter and change it through the setState()
method, and everything should work as expected.
I remend this article.
Tip: A functional ponent can have state now through Hooks.