2015-09-06 103 views
0

我实际上正在学习reactjs,而我实际上正在开发一个包含在名为TODO的“父组件”内的小T​​ODO列表。Reactjs,父组件,状态和道具

在这个父类的内部,我想从关注的存储中获取TODO的当前状态,然后将此状态作为属性传递给子组件。

问题是,我不知道在哪里初始化我的父状态值。其实,我使用ES6语法,所以我没有getInitialState()函数。它写在文档中,我应该使用组件构造函数来初始化这些状态值。

事实是,如果我想初始化我的构造函数内部的状态,this.context(Fluxible Context)实际上是未定义的。

我决定移动componentDidMount中的初始化,但它似乎是反模式,我需要另一种解决方案。你可以帮我吗 ?

这里是我的实际代码:

import React from 'react'; 
import TodoTable from './TodoTable'; 
import ListStore from '../stores/ListStore'; 

class Todo extends React.Component { 

    constructor(props){ 
    super(props); 
    this.state = {listItem:[]}; 
    this._onStoreChange = this._onStoreChange.bind(this); 
    } 

    static contextTypes = { 
     executeAction: React.PropTypes.func.isRequired, 
     getStore: React.PropTypes.func.isRequired 
    }; 

    componentDidMount() { 
     this.setState(this.getStoreState()); // this is what I need to move inside of the constructor 
     this.context.getStore(ListStore).addChangeListener(this._onStoreChange); 
    } 

    componentWillUnmount() { 
     this.context.getStore(ListStore).removeChangeListener(this._onStoreChange); 
    } 

    _onStoreChange() { 
    this.setState(this.getStoreState()); 
} 

    getStoreState() { 
     return { 
      listItem: this.context.getStore(ListStore).getItems() // gives undefined 
     } 
    } 

    add(e){ 
    this.context.executeAction(function (actionContext, payload, done) { 
     actionContext.dispatch('ADD_ITEM', {name:'toto', key:new Date().getTime()}); 
    }); 
    } 


    render() { 
    return (
     <div> 
     <button className='waves-effect waves-light btn' onClick={this.add.bind(this)}>Add</button> 
     <TodoTable listItems={this.state.listItem}></TodoTable> 
     </div> 
    ); 
    } 
} 


export default Todo; 
+0

我很好奇,你在哪里读到,在componentDidMount方法中获取或设置'state'是一个_anti-pattern_? –

+0

@TahirAhmed,在这里:https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html –

+0

hmm但它在那篇文章中提到了'componentDidMount'?我的意思是我在我的项目中所做的几乎与你正在做的一样,即在'componentDidMount'函数内使用'this.setState(...)',直到现在,我认为使用它就好了。我现在很好奇别人怎么看,因为我个人认为没有任何问题。 –

回答

1

正如你应该从Fluxible addons受益变化无常的用户:

以下示例将侦听FooStore和BarStore中的更改,并在实例化时将foo和bar作为道具传递给Component。

class Component extends React.Component { 
    render() { 
     return (
      <ul> 
       <li>{this.props.foo}</li> 
       <li>{this.props.bar}</li> 
      </ul> 
     ); 
    } 
} 

Component = connectToStores(Component, [FooStore, BarStore], (context, props) => ({ 
    foo: context.getStore(FooStore).getFoo(), 
    bar: context.getStore(BarStore).getBar() 
})); 

export default Component; 

查看fluxible example了解更多详情。代码exсerpt:

var connectToStores = require('fluxible-addons-react/connectToStores'); 
var TodoStore = require('../stores/TodoStore'); 
... 

TodoApp = connectToStores(TodoApp, [TodoStore], function (context, props) { 
    return { 
     items: context.getStore(TodoStore).getAll() 
    }; 
}); 

因为你不会需要调用的setState结果,所有的存储数据将在组件的道具。

+0

我想知道是否有可能使我们的反应组件中的通量分离?你认为创建reactjs组件,导出它们,以及在另一个文件中导入时,我们是否将它装饰到另一个文件中是一个好主意?因此,我们的reactjs组件可以很容易地导出,装饰仅在通量项目 – mfrachet

+0

中阅读本文https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0。你应该保持转储组件不知道通量(它们只能在道具和自己的状态下运行),只有顶级智能组件才会有一些逻辑来与流通商店集成 –

+0

所以我的解决方案似乎是一件好事,即使对于父组件也没有? – mfrachet