2016-11-18 3 views
3

Я довольно новичок, чтобы реагировать и бороться с обновлением пользовательского компонента с помощью componentDidMount и setState, что, кажется, рекомендуется для этого. Ниже приведен пример (включает в себя вызов axios API для получения данных):React: componentDidMount + setState не перерисовывает компонент

import React from 'react'; 
import {MyComponent} from 'my_component'; 
import axios from 'axios'; 


export default class Example extends React.Component { 
    constructor(props) { 
     super(props); 

     this.state = { 
      data: [] 
     }; 
    } 

    GetData() { 
     return axios.get('http://localhost:5000/<route>'); 
    } 

    componentDidMount() { 
     this.GetData().then(
       (resp) => { 
        this.setState(
         {data: resp.data} 
        ) 
       } 
      ) 
    } 

    render() { 
     return (
      <MyComponent data={this.state.data} /> 
     ); 
    } 
} 

Doing console.log(this.state.data) чуть ниже render() показывает, что this.state.data действительно обновляется (от [] к тому, что возвращается API). Однако проблема заключается в том, что MyComponent не отображается заново componentDidMount. Из комментариев в Facebook:

Состояние установки в этом методе приведет к повторному рендерингу.

Это не кажется, что в данном случае: Конструктор MyComponent только вызывается один раз (где this.props.data = []) и компонент не получает оказывается снова. Мне было бы здорово, если бы кто-нибудь мог объяснить, почему это так, и есть ли решение или совсем другой способ получить обновление.

UPDATE

Я добавил код для MyComponent (минус некоторые неуместные особенности, как указано ...). console.log(data_array) печатает пустой массив.

import React from 'react'; 

class DataWrapper { 
    constructor(data) { 
    this._data = data; 
    } 

    getSize() { 
    return this._data.length; 
    } 

    ... 
} 


export class MyComponent extends React.Component { 
     constructor(props) { 
     super(props); 

     this._dataWrapper = new DataWrapper(this.props.data); 

     this.state = { 
      data_array: this._dataWrapper, 
     }; 

     } 

    render() { 
     var {data_array} = this.state; 
     console.log(data_array); 
     return (
       ... 
     ); 
    } 
} 
+0

Можете ли вы показать код для 'MyComponent'? То, что вы делаете в компоненте контейнера, выглядит правильно, но что-то странное может происходить внутри дочернего компонента. –

+3

Конструктор не должен вызываться более одного раза. React уже создал объект, ему не нужно делать это снова. Если вы зарегистрируете что-то в 'componentWillReceiveProps', вы увидите, что работаете нормально. И если MyComponent выдает что-то в 'this.props.data', то это будет обновляться. –

+0

Да, почему нужно снова вызвать конструктор? Попробуйте помещать console.log в рендеринг, чтобы подтвердить, что он отображает дважды. – Conan

ответ

2

Вы стать жертвой this antipattern.

В MyComponent конструктор, который только получает называется первый раз монтирует, сдадите пустой массив через new DataWrapper и теперь у вас есть некоторое местное государство, которое никогда не будет обновляться нет независимо от того, что делает ваш родитель.

Всегда лучше иметь один источник истины, только один объект состояния в любом месте (особенно для таких вещей, как ответы ajax), и передавать их через опоры. На самом деле, вы можете даже написать MyComponent как простую функцию, а не класс.

class Example extends Component { 
    state = { data: [] } 

    GetData() { .. } 

    componentDidMount() { 
    this.GetData().then(res => 
     this.setState({data: new DataWrapper(res.data)}) 
    ) 
    } 

    render() { return <MyComponent data={this.state.data} /> } 
} 

... 

function MyComponent (props) { 
    // props.data will update when your parent calls setState 
    // you can also call DataWrapper here if you need MyComponent specific wrapper 
    return (
    <div>..</div> 
) 
} 
Смежные вопросы