最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Understanding async React rendering - Stack Overflow

programmeradmin6浏览0评论

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 if numbers === [0], something like this – Robin Métral Commented Mar 13, 2019 at 13:17
Add a ment  | 

5 Answers 5

Reset to default 2

Your 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.

发布评论

评论列表(0)

  1. 暂无评论