2016-12-09 2 views
0

reactjs에서 상태와 관련된 몇 가지 어려움에 직면하고 있습니다. ComponentWillMount는 컴포넌트가 렌더링되기 전에 ajax 호출로 데이터를로드하는 곳입니다. 나는로드 된 데이터가있는 패널 스택을 채우고 선상에 보여주는 간단한 간단한 프로젝트를 가지고있다. 그러나 ajax 호출의 데이터는 구성 요소 렌더링 전에 설정되지 않으며 이로 인해 빈 배열이있는 보드가 렌더링됩니다.componentWillMount가 렌더링 전에 완료되지 않았습니다.

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')); 
다음과 같이 문제의 뿌리입니다

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> 
    ); 
    } 
    } 

및 이사회 클래스 등 때라도 내 완전한 소스입니다

Board.js 클래스에서 볼 수 있듯이 렌더 함수에서 배열을 초기화 한 다음 componentWillMount를 완료 한 후에 발생할 것으로 예상되는 뉴스 배열을 채우기 위해 componentWillMount를 사용하지만 내 경우에는 th 렌더링이 발생하면 배열이 비어 있습니다. 어떤 생각?

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

나는 또한 componentDidMount 그것을 시도했지만 작동하지 않았다 같은 문제

+0

당신이 설명하는 것은 비동기 함수 호출의 예상 결과입니다. 어디에서 호출하든 관계없이 반응주기는 서버 콜백을 기다리지 않고 렌더링됩니다. 동기 호출 (좋지는 않음)을 시도하거나 AJAX 호출을 사용하여 컴포넌트를 호출 한 다음 그 결과를 'Board'에 소품으로 전달해야합니다. –

답변

1

componentWillMount()은 렌더링 전에 완료되지만 ajax는 비동기이기 때문에 요청이 완료 될 때까지 실행되지 않습니다.

this.state = ...을 사용하여 상태를 설정하면 안됩니다. 대신 다음을 사용하십시오.

this.setState({news: arr}); 

값을 설정하고 구성 요소와 모든 하위를 렌더링하도록 트리거합니다. null 데이터를 잘 처리 할 수 ​​있도록 렌더링 함수를 작성하면 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와 function(){}.bind(this)

+0

'this.state'를 잘 잡습니다. 또한 성공 콜백의 익명 함수에'this.state'가 있다는 것을 알았습니다. '이'는 당신이 기대하는 바가 거의 없을 가능성이 있기 때문에 다른 방법으로 국가에 접근해야합니다. –

+0

@Sandwichz 잘 잡습니다. 나는 바인딩 기능이 종종 내 마음을 건너 뛸 수있는 화살표 기능을 사용하는 데 익숙하다. 나는 예를 들어 업데이트 할 것이다. –

+0

고마워 .bind()의 역할에 대해 설명해 주시겠습니까? –

1

async ... ajax 호출을하고 있습니다 ... 정의에 따르면 Ajax의 응답을 기다리지 않고 코드를 계속 실행합니다.

$ .ajax 옵션에서 async : false를 설정하여 동기를 설정할 수 있습니다.