具有内部隔离Redux存储的可恢复组件

时间:2016-05-04 16:42:04

标签: reactjs redux react-redux

我正在考虑在React中构建一个非常复杂的图表组件,我希望它可以在许多不同的项目中恢复。毋庸置疑,像这样的组件具有需要以某种方式管理的多种状态。

Redux似乎非常适合这种情况,但如果我只是将顶级容器包装在带有自定义存储的Provider中......如果包含该组件,组件的内部redux存储不会干扰全局应用程序状态在更大的React / Redux应用程序中?

import React, { Component } from 'react';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import internalReducer from './reducer';

export default class MyReduxComponent extends Component {

    render() {
        const store = createStore(internalReducer, this.props.initialState);
        return <Provider store={store}>
            <Chart />
        </Provider>
    }

}

3 个答案:

答案 0 :(得分:2)

您是否有理由不仅使用React组件状态? Redux旨在用于整个应用程序中需要由多个组件访问的状态。如果您正在管理仅仅意味着由特定组件的后代使用的状态,那么您也可以只使用组件状态 - 在这种情况下不需要Redux。您的组件将以这种方式更加可重用,并且不会依赖于其他依赖项。

答案 1 :(得分:1)

你的组件不应该有自己的内部redux存储,而是有自己的reducer + actionscer / action creators,reducer知道,所以它可以很容易地与现有的redux应用程序集成:

export class Scheduler {
// Support for Scheduler
@Input() resources: any[];   
@Input() resourceAreaWidth: string;            
@Input() resourceLabelText: string; 
// End Support for Scheduler

// Added functionality
@Input() slotLabelFormat: any;
@Input() titleFormat: any;
@Input() eventBackgroundColor: any;
// End added properties

@Input() events: any[];
............
............
ngAfterViewInit() {
    this.schedule = jQuery(this.el.nativeElement.children[0]);
    this.schedule.fullCalendar({
        resources: this.resources,
        resourceAreaWidth: this.resourceAreaWidth,
        resourceLabelText: this.resourceLabelText,
        titleFormat: this.titleFormat,
        slotLabelFormat: this.slotLabelFormat,
        eventBackgroundColor: this.eventBackgroundColor,
        theme: true,
        header: this.header,
...........

您的库的用户可能不需要明确使用任何操作,只需包括reducer就足够了,因此可以在应用程序的任何位置访问图表状态。

此外,如果您需要以某种方式增加动作调用,可以编写一些中间件。

http://redux.js.org/docs/advanced/Middleware.html

答案 2 :(得分:1)

我认为我在顶部组件中使用childContextTypessetState找到了解决问题的一种非常好的方法。这允许任何深度的子组件只是&#34; import&#34;他们需要的上下文行动。 (这消除了通过多个嵌套组件将回调作为道具传递的需要)。

Example on JSBin

顶级组件可能如下所示

export default class ReusableComponent extends Component {

  // Define the public API interface to child components
  static childContextTypes = {
    // expose component state store
    store: PropTypes.object,
    // actions
    setFoo: PropTypes.func,
    setBar: PropTypes.func
  };

  // Set initial state, can be overriden by props
  constructor(props) {
    super(props)
    this.state = {
      foo: 'My Foo',
      ...props
    }
  }

  // Define methods for public API 
  getChildContext() {
    return {
      store: this.state,
      setFoo: this.setFoo.bind(this),
      setBar: this.setBar.bind(this)
    };
  }

  // Reducer for action setFoo
  setFoo(foo) {
    this.setState({ foo })
  }

  // Just render components, no need for passing props
  render() {
    return <div>
      <UpdateFooComponent />
      </div>
  }

}

和儿童组件

class UpdateFooComponent extends Component {

  // 'import' the store and actions you need from top component
  static contextTypes = {
    store: PropTypes.object,
    setFoo: PropTypes.func
  };

  clickHandler(e) {
    this.context.setFoo('Hello from subcomponent');
  }

  render() {
    const { foo } = this.context.store;
    return <div>
      <button onClick={::this.clickHandler}>Update foo</button>
      <p><strong>foo:</strong> {foo}</p>
    </div>
  }

}