我正在考虑在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>
}
}
答案 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就足够了,因此可以在应用程序的任何位置访问图表状态。
此外,如果您需要以某种方式增加动作调用,可以编写一些中间件。
答案 2 :(得分:1)
我认为我在顶部组件中使用childContextTypes
和setState
找到了解决问题的一种非常好的方法。这允许任何深度的子组件只是&#34; import&#34;他们需要的上下文行动。 (这消除了通过多个嵌套组件将回调作为道具传递的需要)。
顶级组件可能如下所示
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>
}
}