反应,在调用特定的 redux 操作时打开所有扩展器

React, open all expanders when particular redux action is called

基本上我想要实现的是在有人开始提交时打开所有扩展器。这听起来很简单,但我想出的解决方案却很难看。调度操作时,它会更改 redux 中的状态,以向组件发出信号,表明它必须打开扩展器,然后立即调用另一个操作来重置缩减器状态。我正在使用 redux observable,所以我也可以在我的 epics 中调用开始和结束只是为了向组件发出信号。然而这种方法看起来很奇怪,有没有更好的方法来通知组件做一些动作?这是我下面的伪代码:

class ExpanderWrapper : React.Component<any,any>
{
    state = {expanded:false}

    componentWillReceiveProps(newProps)
    {
        if(newProps.forceExpand) {
         this.setState({expanded:true});
          this.props.forceExpandEnded();
        }
    }


     render() {
       return( <Expander expanded={this.state.expanded} 
                onExpandChange={()=>this.setState({expanded:false)} />
     }
}


connect(ExpandWrapper,... map forceExpand and forceExpandEnded() here)


reducer(state,action)
{
  if(action === forceExpandStarted)
   return {...state,forceExpand:true}
  if(action === forceExpandEnded)
   return {...state,forceExpand:false}
}

我认为这里的问题是如何让组件观察特定于应用程序的 events/signals 当似乎不需要额外的状态时。

您的解决方案涉及将 forceExpand 信号添加到应用程序状态,这可能是丑陋所在。您被迫连接到状态树以获取该信号,然后为当前呈现的每个 <Expander> 重置它。

另一种方法是在没有 redux-observable 的情况下使用 RxJS。使用此解决方案,您可以创建一个 Subject,只要相关操作被推送到 redux 存储,它就会发出。然后,您在您的组件中订阅和取消订阅此 Observable

一个简单粗暴的例子:

// in some module
export const ExpandSignal = new Rx.Subject();
export const ExpandSignalActionTypes = [ ... ];

// middleware that looks at the redux actions
const signalMiddleware = store => next => action => {
  if (ExpandSignalActionTypes.includes(action.type))
    ExpandSignal.next();

  return next(action);
};

// implement with wrapper, or integrate into existing component
class ExpandWrapper extends React.Component {
  state = { expanded: false };

  componentDidMount() {
    this.subscription = ExpandSignal.subscribe(() => this.setState({ expanded: true });
  }

  componentWillUnmount() {
    this.subscription.unsubscribe();
  }

  render() {
    return (
      <Expander expanded={this.state.expanded}
                onExpandedChanged={() => this.setState({ expanded: false })} />
    )
  }
}