当调用特定的redux动作时,React,打开所有扩展器

时间:2017-11-27 17:47:54

标签: reactjs redux redux-observable

基本上我想要实现的是在有人开始提交时打开所有扩展器。听起来很简单,但我遇到的解决方案非常难看。当调度action时,它会将redux中的状态更改为必须打开扩展器的信号组件,然后立即调用另一个操作来重置reducer状态。我使用了redux observable,所以我也可以在我的史诗中调用start和end来表示组件。然而,这种方法似乎很奇怪,有没有更好的方法来发信号通知组件做一些动作?这是我的伪代码:

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}
}

1 个答案:

答案 0 :(得分:1)

我认为这里的问题是当附加状态似乎没有必要时,如何让组件观察特定于应用程序的事件/信号。

您的解决方案涉及将char *a[] = {"quick", "brown", "fox", "jumps"}; int n = 0; char buf[100]; for (int i = 0 ; i != 4 ; i++) { n += sprintf(buf+n, "%s%c", a[i], 0); } 信号添加到应用程序状态,这可能是丑陋所在的位置。您被迫挂入状态树以获取该信号,然后为当前呈现的每个forceExpand重置它。

替代方案可以是在没有redux-observable的情况下使用RxJS。使用此解决方案,您可以创建<Expander>,只要将相关操作推送到redux存储,就会发出Subject。然后,您订阅并取消订阅组件中的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 })} />
    )
  }
}