如何管理UI反馈?

时间:2015-07-24 17:48:44

标签: reactjs design-patterns imperative-programming

是否存在用于管理用户与单个组件交互的已建立模式,例如显示加载器微调器,在表单保存/加载时禁用输入字段等?

我发现自己在我的商店里做了以下工作,以使组件与任何隐含状态保持一定的分离:

IFS=. read -p "Please enter hostname: " -a hostname
echo "${hostname[0]}"

基本上,我只是发出一个事件,说某些动作即将发生,然后我执行动作(进行API调用等),然后在动作完成时发出另一个事件。

在组件内部,我可以订阅function CampaignStore() { EventEmitter.call(this); AppDispatcher.register(payload => { switch (payload.type) { // [#1] ---------------v (main action) case CampaignContants.SAVE: // [#2] ------------------------v (prepare for the main action) this.emit(CampaignContants.WILL_SAVE); const data = payload.data; if (data.id) { // [#3] ---v (perform main action in store) updateCampaign(payload.data).then(_ => { // [#4] ------------------------v (after main action) this.emit(CampaignContants.DID_SAVE, 0) }); } else { insertCampaign(payload.data).then(campaignId => this.emit(CampaignContants.DID_SAVE, campaignId)); } break; // ... } } } 事件,渲染所有微调器等,然后在WILL_<action>被触发时清除屏幕。虽然这似乎有效,但它确实感觉很漂亮和重复,以及超级凌乱(太多的状态,只存在根据动作的位置调整UI(DID_<action>和* {{1}之间}。

WILL_<action>

3 个答案:

答案 0 :(得分:1)

我认为您最好使用componentWillMountcomponentDidMountcomponentWillUpdatecomponentWillUnmount等生命周期方法。使用这些方法,您可以检查前一个/当前/下一个道具/状态(取决于方法)并对其做出响应。这样你的商店只处理你的状态,你的组件变得更纯净。

答案 1 :(得分:1)

我们发现一个简单的装载容器组件在这里有所帮助。 所以像这样:

const LoadingContainer = React.createClass({
    getDefaultProps: function() {
      return {isLoadedCheck:(res) => res.data!=null }
    },
    getInitialState: function() {
      return {isLoaded:false, errors:[]}
    },
    componentDidMount: function() {
      if(this.props.initialLoad) { this.props.initialLoad(); }
      if(this.props.changeListener) { this.props.changeListener(this.onChange); }
    },
    onChange: function() {
      let res = this.props.loadData();
      this.setState({errors: res.errors, isLoaded: this.props.isLoadedCheck(res)});
    },
    render: function() {
      if(!this.state.isLoaded) {
        let errors = this.state.errors && (<div>{this.state.errors.length} errors</div>)
        return (<div>{errors}<LoadingGraphic /> </div>)
      }
      return <div>{this.props.children}</div>
    }
  });

  const Wrapper = React.createClass({
    getDefaultProps: function() {
      return {id:23}
    },
    render: function() {
      let initialLoad = () => someActionCreator.getData(this.props.id);
      let loadData = () => someStore.getData(this.props.id);
      let changeListener = (fn) => someStore.onChange(fn);
      return (<div><LoadingContainer initialLoad={initialLoad}
        changeListener={changeListener}
        loadData={loadData}
        isLoadedCheck={(res) => res.someData != null}><SomeComponent id={this.props.id} /></LoadingContainer></div>)
    }
  });

虽然它添加了另一个无状态包装器,但它提供了一种干净的方法来确保您的组件不仅仅在mount上加载,并且是一个显示api反馈等的公共位置。 并且随着反应14,这些纯粹的无状态包装正在得到一点推动,随之而来的改进,所以我们发现它很好地扩展

答案 2 :(得分:-1)

这种模式可以帮助您使用各个组件来管理用户交互

var MyComponent = React.createClass({
getInitialState: function() {
  return {
    item: [],
    loading: true,
  };
},
componentDidMount: function() {
  //Make your API calls here
  var self = this;
  $.ajax({
    method: 'GET',
    url: 'http://jsonplaceholder.typicode.com/posts/1',
    success: function(data) {
      if (self.isMounted()) {
        self.setState({
          item: data,
          loading: false
        });
      }
    }
  });
},
render: function() {
  var componentContent = null;
  if (this.state.loading) {
    componentContent = (<div className="loader"></div>);
  } else {
    componentContent = (
      <div>
        <h4>{this.state.item.title}</h4>
        <p>{this.state.item.body}</p>
      </div>
    );
  }
  return componentContent;
}});