#javascript #reactjs #rendering
#javascript #reactjs #рендеринг
Вопрос:
Я новичок в изучении React, и мне интересно, почему следующий код работает не так, как ожидалось. Я думал, что это будет отображаться, The numbers: 0123
но это только отображается 0
. Я также использовал тот же подход с компонентом на основе классов и использовал хуки, и я все еще получаю тот же результат. Чего я не понимаю в рендеринге react с использованием асинхронного кода?
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);
Комментарии:
1. Я также создал несколько песочниц для кода, чтобы протестировать его: это для приведенного выше примера: codesandbox.io/s/nwlvnxxqkj Это классовый подход: codesandbox.io/s/wqm2z43on7 И это с использованием крючков: codesandbox.io/s/43058qw614
2. как указал @sjahan ниже, примеры состояния и перехватов не сработали, потому что я пытался загрузить незащищенный json на защищенную страницу. Обновлен для использования https, и теперь он работает!
3. Примечание стороны, вы также можете вернуть
null
во время загрузки вашего запроса, проверив, есть лиnumbers === [0]
, что-то вроде этого
Ответ №1:
Ваш код выводит 0, потому что это значение переменной number
во время рендеринга.
Вы используете следующий код:
fetch("some.url")
.then(res => res.json())
.then(list => {
for (let n of list) {
numbers.push(n);
}
});
получить новое значение асинхронно, но это не будет иметь никакого эффекта: компонент уже рендерен.
Если вы хотите обновить его, вы должны ввести свой номер переменной в state
и использовать setState()
для передачи нового значения.
Если вы хотите сохранить функциональные компоненты, вам следует использовать совершенно новую функцию hooks, которая должна дать вам эквивалент setState
.
Комментарии:
1. Я попробовал
setState
подход, но получил тот же результат. Пожалуйста, посмотрите мой комментарий к исходному вопросу.2. Это должно сработать, но ваше обещание не выполняется. Пожалуйста, исправьте свои фрагменты 😉
3. Это действительно работает. По-видимому, это заблокировало загрузку небезопасного URL, который я использовал для издевательства. Теперь я чувствую себя глупо. Спасибо!
Ответ №2:
Вы можете использовать useState
перехват для создания фрагмента состояния, представляющего собой массив, и получить список чисел с помощью useEffect
перехвата и обновить числа по завершении этого запроса.
Пример
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.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Ответ №3:
Приведенный выше фрагмент кода поможет вам понять правильное использование немого (он же без состояния) и интеллектуального (с сохранением состояния) компонента.
Начните думать об этом, используя жизненные циклы react, чтобы сделать его еще более понятным
В приведенном выше фрагменте render() уже выполнялся с начальным значением
let numbers = [0];
и поскольку изменения не выполняются в состоянии или реквизитах, повторный рендеринг не происходит, и вы не получаете желаемого результата.
Решение —
- Сделайте функциональный компонент компонентом класса, т. е. сделайте его интеллектуальным компонентом или используйте перехватчики (useState), чтобы сделать его интеллектуальным компонентом.
- Используйте детализацию реквизитов, т. е. вычислите значение в родительском компоненте и передайте его дочернему компоненту с использованием реквизитов
Воспользуйтесь этим как возможностью подготовить свое мышление к «МЫШЛЕНИЮ в REACT»
Ответ №4:
При создании интерфейса рендеринг является наиболее важной процедурой, с которой приходится сталкиваться программисту. Метод render) ( в React является единственным методом, необходимым в компоненте класса, и отвечает за определение вида, который будет отображаться в окне браузера. Существует множество тонкостей в том, как работает этот подход, в сочетании с продуманным способом, которым React использует свою концепцию виртуального DOM, и знание их принесло бы огромную пользу любому начинающему разработчику React. Для демонстрации обсуждаемых привычек я буду ссылаться на этот codepen. render() 101 Render) (прежде всего, не вызывается пользователем. Это часть жизненного цикла компонента React и вызывается React на разных этапах приложения, обычно при первом создании экземпляра компонента React или при новом изменении состояния компонента. Рендеринг не принимает никаких аргументов и возвращает JSX.Element, который содержит иерархию представлений текущего компонента. Эта иерархия представлений позже будет преобразована в HTML и показана в окне браузера. В рамках жизненного цикла это сценарии, в которых вызывается рендеринг:
После первого создания экземпляра компонента React, следующего за вызовом constructor(). После обновления реквизитов компонента после вызова setState() я бы порекомендовал эту статью- https://en.wikipedia.org/wiki/React_ (web_framework) сначала нужно разобраться в основах.
Ответ №5:
Это функциональный компонент, или stateless
component . У него нет собственного состояния. Таким образом, если вы измените значение переменной numbers, состояние компонента не изменится. Если вы действительно хотите использовать функциональный компонент, вам следует написать логику извлечения URL-адреса и обновления состояния в родительском компоненте с отслеживанием состояния и передать numbers
переменную в качестве prop компоненту без состояния.
В противном случае, если вам не нужно использовать функциональный компонент. Измените его на компонент класса и поместите переменную numbers в качестве параметра состояния и измените ее с помощью setState()
метода, и все должно работать так, как ожидалось.
Я рекомендую эту статью.
Совет: Функциональный компонент теперь может изменять состояние с помощью перехватов.