2016-12-09 4 views
0

У меня возникли некоторые трудности, связанные с состоянием в реакции. Насколько я знаю, компонентWillMount - это место для загрузки данных с помощью ajax-вызова, прежде чем компоненты получат визуализацию. У меня есть простой простой проект, который заполняет стек панелей загруженными данными и показывает их на борту. Однако данные из ajax-вызова не устанавливаются перед рендерингом компонента, и это приводит к рендерингу платы с пустым массивом. Follwoing является моим полным источником:componentWillMount не заканчивается перед рендером

import React from "react"; 
export class Panel extends React.Component{ 
render() { 
    return (
    <div> 
     <div className="row panel"> 
      <div className="col-sm-12 header">sfsfsf</div> 
      <div className="col-sm-12 body">fsdfsfs</div> 
      <div className="col-sm-12 footer">fasfaf</div> 
     </div> 
    </div> 
    ); 
    } 
    } 

и Совет класса, который является корень проблемы заключается в следующем:

import React from "react"; 
import {Panel} from "./Panel"; 
export class Board extends React.Component{ 
constructor(props){ 
    super(); 
    this.state={news: []}; 
} 
componentWillMount(){ 
    this.state={news: []}; 
    $.ajax({ 
     url: "http://localhost:3003/json.txt", 
     dataType: 'json', 
     cache: false, 
     success: function(data) { 
      var arr=[]; 
      for (var key in data) { 
       arr.push(data[key]); 
       console.log(data[key]); 
      } 
      this.state={news: arr}; 
     }}); 
    } 
    render() { 
    return (
     <div> 
      { 
       this.state.news.map((item,i)=> <Panel key="i"/>) 
      } 
     </div> 
    ); 
    } 
} 

Также последний класс index.js:

import React from "react"; 
import {render} from "react-dom"; 
import {Board} from "./component/Board"; 

class App extends React.Component{ 

    render(){ 
    return(
     <div> 

      <Board/> 

     </div> 

    ); 
    } 

} 

render(<App/>, document.getElementById('middle')); 

Итак, как вы можете видеть в классе Board.js, я инициализирую свой массив в функции рендеринга, а затем я использую компонент componentWillMount для заполнения массива новостей, который, как я ожидаю, произойдет после завершения компонента componentWillMount, но в моем случае th При выполнении рендеринга массив пуст. Есть идеи?

********* UPDATE ***************

Я также пробовал с componentDidMount, но он не работает и та же проблема

+0

То, что вы описываете, является ожидаемым результатом вызова асинхронной функции. Независимо от того, где вы это называете, жизненный цикл React будет отображаться без ожидания вашего обратного вызова сервера. Вы должны попробовать либо синхронный вызов (не очень хороший), либо принять вызов AJAX на один компонент, а затем передать результаты на ваш «Совет» в качестве реквизита. –

ответ

1

componentWillMount() заканчивается перед рендером, но поскольку ajax является асинхронным, он не будет выполняться до тех пор, пока запрос не завершится.

Нельзя установить состояние, используя this.state = .... Вместо этого используйте:

this.setState({news: arr}); 

Это установит значение и вызовет отображение компонента и всех дочерних элементов. Просто напишите свою функцию рендеринга, чтобы хорошо обрабатывать нулевые данные, и вы получите ожидаемый результат, не блокируя выполнение JS.

Как предложено здесь с надлежащим обязательными:

import React from "react"; 
import {Panel} from "./Panel"; 
export class Board extends React.Component{ 
    constructor(props){ 
    super(); 
    } 

    getInitialState() { 
    return {news: []}; 
    } 

    componentWillMount(){ 
    $.ajax({ 
     url: "http://localhost:3003/json.txt", 
     dataType: 'json', 
     cache: false, 
     success: (data) => { 
     var arr=[]; 
     for (var key in data) { 
      arr.push(data[key]); 
      console.log(data[key]); 
     } 
     this.setState({news: arr}); 
     } 
    }); 
    } 
    render() { 
    return (
     <div> 
      { 
       this.state.news.map((item,i)=> <Panel key="i"/>) 
      } 
     </div> 
    ); 
    } 
} 

Функция стрелка обрабатывает привязки. Simmilar to function(){}.bind(this)

+0

Хороший улов на 'this.state'. Также я заметил, что в анонимной функции при успешном обратном вызове есть «this.state». Вам нужно будет получить доступ к состоянию по-другому, поскольку «это», скорее всего, не будет тем, что вы ожидаете. –

+0

@Sandwichz Хороший улов. Я так привык к использованию функций стрелок, которые часто связывают вещи. Я обновлю, мой пример. –

+0

Спасибо, пожалуйста, объясните роль .bind() здесь? –

1

Вы выполняете вызов ajax, который является асинхронным ... По определению он будет продолжать выполнять код, не дожидаясь ответа ajax.

вы можете включить эту синхронность, установив async: false в параметрах $ .ajax.