React:高阶组件:你可以孩子状态吗

React: Higher Order Components: Can you can childs state

我正在尝试从 mixins 重构为 HOC,这样我就可以升级到最新的 React(我目前正在使用 React 13/ES5)。当我的组件加载时,mixin 能够访问数据 object、this.data,该数据具有 query 属性 和路由。

React.createClass({
  mixins: [myMixin],
  data: {
    query: "/api/foo"
  },
  componentDidUpdate(): function(){
  }
  ...
}

componentDidMountmixin 中,它将查询该路由,取回数据并将其置于状态。

var myMixin = React.createClass({
  componentDidMount(): function(){
    this.fetchData(this.data.query)
  }
  fetchData(query) {
    // fetch the data
  }
  ...
}

这从我的组件中提取了大量样板文件。我不必在每个组件上 运行 componentDidMount,只需要 data object.

我在整个项目中都散布了这个 mixin。它实际上做的远不止于此,但为了举例,我只是想简化它。

HOC 来了。我从 data 中取出所有的东西并放入 getInitialState 中。现在我已经 data 现在包装组件的状态,我如何访问它?就像我的 mixin 一样,我希望我的 HOC 处理我的 componentDidMount,访问 data.query 并获取数据。我不想重写每个组件以获得 componentDidMount.

PS- 我通常使用最新版本的 React 和 ES6,如果有人能告诉我为什么 mixin 可以 this.data 而我的组件不能,那将非常有帮助。在最新版本的 React 中,你不能像这样在 render() 之外定义 object。

React 不鼓励从组件外部更改 statestate 归组件所有,因此只有组件可以控制它。

来自React documentation

State is similar to props, but it is private and fully controlled by the component.

所以你可以做的是使用 props 而不是 state。对于给定的示例,您可以按如下方式编写高阶组件。但是您的 Child 组件应该更改为从 props 而不是 state.

呈现数据
function HOC(WrappedComponent){

  return React.createClass({

    getInitialState: function() {
      return { data: null };
    },

    componentDidMount: function(){
      this.fetchData(WrappedComponent.prototype.data.query)
    },

    fetchData: function(query){
     // Fetching data first
     // Then set the state with data
     this.setState({data:data});
    },

    render: function() {
      var props = Object.assign({}, this.props, this.state);
      return React.createElement(WrappedComponent, props);
    }

  });

}

var HOCChild = HOC(Child);

PS- I normally use the newest version of React and ES6, if anyone can tell me why the mixin could do this.data and my component couldn't that would be very helpful. In the newest version of React you can't define an object outside of render() like that.

通常,React 组件定义为 ES6 class。 ES6 classes 不支持静态或实例属性。但是您可以像这样在承包商内部定义实例属性。

class A{
  constructor(){
    this.foo = "foo"
  }
}