2017-01-06 7 views
1

React 구성 요소에 대한 초기 데이터를 얻기 위해 디스패치를 ​​호출하는 가장 좋은 방법은 무엇입니까? 내 이해는 ComponentWillMount 렌더링 전에 호출됩니다. 따라서 이론적으로 ComponentWillMount에서 dispatch를 호출하면 렌더링 할 때까지 ComponentDidMount를 사용하여 구성 요소의 소품에 데이터가 있어야합니다. 나는 그것을 보지 않고있다.React Redux Dispatch

렌더링이 두 번 호출되는 것을보고 있는데, 구성 요소가 초기화 될 때 렌더링이 두 번 호출되며, 소품의 데이터에 액세스 할 수 없습니다. 디스패치는 실제로 두 번째 렌더링까지 호출되지 않습니다. 기본적으로 초기에 구성 요소를 설정할 때 디스패치를 ​​호출하는 가장 좋은 방법을 밝혀주는 것이 중요합니다. 필자는 컨테이너 구성 요소를 사용하여 디스패치에서 데이터를 가져온 다음 하위 구성 요소에 소품으로 전달하기 위해 다음과 같은 작업을 수행하려고합니다. 그러나 ContainerComponent에서 일부 상태 변수를 초기화 한 다음 ChildComponent에 전달합니다. 문제는 초기화 할 상태 변수가 dispatch에서 반환 된 데이터에 따라 다르다는 것이고 이상적으로는 ComponentWillMount 또는 ComponentDidMount에서 초기화를 수행하는 것이 좋습니다. 얻기

What is the best way to call a dispatch to get initial data on a React component?

: 나는 당신의 주요 질문은 생각

import axios from 'axios'; 

export const GET_TRANSACTIONS = 'GET_TRANSACTIONS'; 

export function getTransactions(year) { 
return function(dispatch) { 
    axios.get(`http://localhost:3001/api/transfilter?year=${year}&grouping=2`) 
    .then(response => { 
    dispatch({ 
     type: GET_TRANSACTIONS, 
     payload: response.data, 
     selectedYear: year 
    }); 
    }) 
    .catch((error) => { 
    console.log(error); 
    }) 
} 
} 

export const GET_TRANSACTIONS_ALL = 'GET_TRANSACTIONS_ALL'; 

export function getTransactionsAll(year) { 
return function(dispatch) { 
    axios.get(`http://localhost:3001/api/trans?limit=20`) 
    .then(response => { 

    dispatch({ 
     type: GET_TRANSACTIONS_ALL, 
     payload: response.data 
    }); 
    }) 
    .catch((error) => { 
    console.log(error); 
    }) 
} 
} 
+0

우리는 componentDidMount에서 가져 오기 API 데이터 메소드를 호출하고 있습니다. HTML 템플릿에서 컴포넌트를 어떻게 사용하고 있습니까? –

+0

가져 오기가 작동합니다. 모든 것이 작동합니다. 단지 그것을 수행하고 파견 "라이프 사이클"을 더 잘 이해할 수있는 가장 좋은 방법을 알고 싶습니다. 렌더링이 두 번 호출되고 두 번째 렌더링이 호출 될 때까지 데이터를 사용할 수 없기 때문에 가져 오기가 실제로 호출되기 때문에 렌더링이 즉시 실행되지 않는 것 같습니다. –

+0

어디서'searchProps'를 전달하고 있습니까? 이 컨테이너 부모 컴포넌트와'get_data' 함수를 보여 주어야합니다. – azium

답변

3

: 여기

import { combineReducers } from 'redux' 

import {GET_TRANSACTIONS } from '../actions/actions.js' 
import {GET_TRANSACTIONS_ALL } from '../actions/actions.js' 

const INITIAL_STATE = { defaultYear: 2016, transactions: []}; 

function get_transactions(state = INITIAL_STATE, action) { 
    // console.log("this is in the reducer: get_transactions"); 
    // console.log(action); 
    switch(action.type) { 
    case GET_TRANSACTIONS: 
     // return { ...state, transactions: action.payload }; 
     return Object.assign({}, state, { 
     transactions: action.payload, 
     selectedYear: action.selectedYear 
     }) 
    default: 
     return state; 
    } 
} 

function get_transactions_all(state = INITIAL_STATE, action) { 
    console.log("this is the value of action in the reducer: get_transactions_all"); 
    console.log(action); 
    switch(action.type) { 
    case GET_TRANSACTIONS_ALL: 
     // return { ...state, transactions: action.payload }; 
     return Object.assign({}, state, { 
     transactions_all: action.payload 
     }) 
     console.log("this is the value of state in the reducer after being set"); 
     console.log(state); 
    default: 
     return state; 
    } 
} 

const rootReducer = combineReducers({ 
    //stateProps: get_transactions, 
    searchProps: get_transactions_all 
}) 

export default rootReducer 

내 작업입니다 : 여기
import React from 'react'; 
import axios from 'axios'; 

import { connect } from 'react-redux'; 
import ChildComponent from './ChildComponent.js'; 

import { getTransactionsAll } from '../actions/actions.js'; 

class ContainerComponent extends React.Component { 
    constructor() { 
    super(); 
    this.state = { 
     acctList:[], 
     acctChecked:[], 
     categoryList:[] 
    } 
} 
    componentWillMount() { 

    console.log("componentWillMount entered"); 

    this.props.get_data(); 
    console.log(this.props.searchProps.transactions_all);//this is undefined meaning the dispatch has not assigned the data yet...?? 

    } 

    componentDidMount() { 
    console.log("componentDidMount entered"); 
    console.log(this.props.searchProps.transactions_all);//this is undefined meaning the dispatch has not assigned the data yet...?? 
} 

    render() { 

    console.log("TransactionManagerContainer render entered"); 
    console.log(this.props.searchProps.transactions_all);//this is undefined the first time around meaning the dispatch has not assigned the data yet...??, but is defined on the second call to render after the dispatch has actually occurred... 

return <ChildComponent 
      data={this.props.searchProps.data}/>; 
} 

const mapStateToProps = (state) => ({ 
    searchProps: state.searchProps 
}); 

export default connect(mapStateToProps, {getTransactionsAll})(TransactionManagerContainer); 

는 상태를 할당 나의 감속기입니다 초기 데이터 요청 (또는 AJAX 요청 일반적으로 ts)은 componentDidMount주기주기 이벤트에 있어야합니다.

이에 대한 몇 가지 이유가 있습니다, 여기에 두 가지 중요하다

  1. 섬유,의 반작용 화해 알고리즘의 다음 구현, 시작 및 성능 혜택을 필요에 따라 렌더링을 중지 할 수있는 기능을 제공합니다. 이것의 절충점 중 하나는 componentWillMount, AJAX 요청을하는 것이 타당 할 수있는 다른 라이프 사이클 이벤트가 "비 결정적"이라는 것입니다. 이것이 의미하는 바는 React가 필요할 때마다 여러 번 componentWillMount를 호출하기 시작할 수 있다는 것입니다. 이것은 분명히 AJAX 요청에 대한 나쁜 공식이 될 것입니다.

  2. 구성 요소가 마운트되기 전에 AJAX 요청이 해결되지 않을 것이라고 보장 할 수 없습니다. 그렇게했다면, 그것은 당신이 마운트되지 않은 구성 요소에 setState를 시도하려고한다는 것을 의미 할 것입니다. 마운트되지 않은 구성 요소는 작동하지 않을뿐만 아니라 React가 당신에게 소리를 지르도록합니다. componentDidMount에서 AJAX를 수행하면 업데이트 할 구성 요소가 있음을 보장합니다.

크레딧 : 나는 here에서, 또한 토론 here이 있음을 알게되었다.

그런 다음, 당신이 제기 한 작은 질문을 많이가 나를 모든 대답하기가 어려울 것이다, 그러나 나는 대부분 충당하기 위해 노력 할게요 :

  • 을 위의 내용을 읽고 나면, 당신을 지금 귀하의 데이터가 undefined 인 이유를 componentWillMountcomponentDidMount으로 이해해야합니다. 이는 데이터가 아직 도착하지 않았기 때문입니다.
  • 구성 요소를 처음으로 렌더링하는 동안 데이터가 undefined 인 것은 정상입니다.초기 렌더링은 데이터 도착 전에 발생합니다.
  • 두 번째 렌더링 중에 데이터가 정의되는 것이 정상입니다. dispatch은 비동기 데이터 반입을 트리거합니다. 데이터가 오면 바로 reducer이 발생하고 구성 요소가 다시 렌더링됩니다 (두 번째 다시 렌더링 됨).
  • 데이터가있는 경우 기본 구성 요소의 하위 구성 요소에 부모 확인 데이터가 필요한 경우 render 데이터가있는 경우에만 조건부로 내부 구성 요소를 전달합니다. 그래서 같이 : 그 작업을해야한다 그래서 반응/nuclearjs 프로젝트

    class ContainerComponent extends React.Component { 
        // ... omitted for brevity 
    
        render() { 
        return (
         { this.props.searchProps.data ? 
          <ChildComponent 
          data={this.props.searchProps.data} /> 
          : <p>Loading</p> 
         } 
        ); 
        } 
    } 
    
+0

개념 설명을 주셔서 감사합니다. 말된다. 그래서 위의 렌더링을 복사하여 붙여 넣으면 오류가 발생합니다 :'111 | 창 ( > 112 | {this.props.searchProps.data | ^는 113 | 115 | :

로드

는 '그렇지 않다 코멘트에 형식을 지정하는 방법이 확실하지 않지만, 본질적으로 this.props에 대한 첫 번째 호출에서 구문 오류가 발생합니다. –

+0

환영합니다. 흠, 확실하지 않습니다 - 오류가 발생하지 않습니다. 'this.props.searchProps'가 정의되지 않았기 때문에 문제가 발생할 수 있습니다. 처음에는 존재하지 않는'props'를 기본값으로 설정하는 것이 좋습니다. 그렇지 않으면 항상'undefined '최초의 렌더링 동안. [기본 소품 선언] (http://stackoverflow.com/documentation/reactjs/6371/react-createclass-vs-extends-react- component/25321/declare-default-props-and-proptypes # t = 201701071958593048809) 문제가 해결되었는지 확인하십시오. –

+0

감사합니다. 나는 당신이 응답 한 나의 다른 포스트에서 건의 한대로 저것을했다. 그리고 기본 소도구를 설정하는 것도 효과가 없습니다. 나는 혼란 스럽다. 마치 내 기본 소품이 무시되는 것 같습니다. 나는 심지어 내 babel.rc에 갔고 내가 2016 초기 설정을했는지 확인했다. 나는 생성자에서 기본 소품을 설정하고 Component.defaultProps를 사용하여 클래스 외부에서이를 수행하는 정적 방법을 시도했다. 나도 처음에 여전히 정의되지 않은 이유로 작동하지 않는 것 같습니다. –

관련 문제