Asynchronous React redux关注点分离

Asynchronous React redux关注点分离,asynchronous,reactjs,q,redux,redux-thunk,Asynchronous,Reactjs,Q,Redux,Redux Thunk,我正在尝试构建一个简单的应用程序来查看美国宇航局“每日图片”服务()发布的照片。当前正在监视按键,然后根据按键是向左、向上、向右或向下的箭头来更改日期(以及异步更改图片)。这将相应地改变以一周或一天表示的日期(想象一下,一次移动一个正方形的日历) 我遇到的问题是:我创建了一个异步操作创建者来获取下一个可能的日期,但是我需要知道应用程序的当前状态以及检索新日期的按键。有没有办法将其封装到action creator中?或者我应该将应用程序状态设置为在应用程序中调用导出的操作创建者的位置,以便让我的

我正在尝试构建一个简单的应用程序来查看美国宇航局“每日图片”服务()发布的照片。当前正在监视按键,然后根据按键是向左、向上、向右或向下的箭头来更改日期(以及异步更改图片)。这将相应地改变以一周或一天表示的日期(想象一下,一次移动一个正方形的日历)

我遇到的问题是:我创建了一个异步操作创建者来获取下一个可能的日期,但是我需要知道应用程序的当前状态以及检索新日期的按键。有没有办法将其封装到action creator中?或者我应该将应用程序状态设置为在应用程序中调用导出的操作创建者的位置,以便让我的操作创建者不知道应用程序的状态?我试图通过为顶级
组件
绑定
componentDidMount
中的keydown函数来实现这一点,但是绑定到应用程序存储区似乎并没有反映出reducer中发生的更改

依赖redux thunk中间件和q的异步逻辑:

// This function needs to know the current state of the application
// I don't seem to be able to pass in a valid representation of the current state
function goGetAPIUrl(date) {
   ...
}

function getAsync(date) {
  return function (dispatch) {
    return goGetAPIUrl(date).then(
      val => dispatch(gotURL(val)),
      error => dispatch(apologize(error))
    );
  };
}

export default function eventuallyGetAsync(event, date) {
  if(event.which == 37...) {
    return getAsync(date);
  } else {
    return {
      type: "NOACTION"
    }
  }
}
下面是gridAppState的顶级绑定,以及在顶级发生的其他一些我不太理解的相关内容

class App extends React.Component {
  componentDidMount() {
    const { gridAppState, actions } = this.props;
    document.addEventListener("keydown", function() {
      actions.eventuallyGetAsync(event, gridAppState.date);
    });
  }
  render() {
    const { gridAppState, actions } = this.props;
    return (
        <GridApp gridAppState={gridAppState} actions={actions} />
    );
  }
}

App.propTypes = {
  actions: PropTypes.object.isRequired,
  gridAppState: PropTypes.object.isRequired
};

function mapStateToProps(state) {
  return {
    gridAppState: state.gridAppState
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(GridActions, dispatch)
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);
类应用程序扩展了React.Component{
componentDidMount(){
const{gridAppState,actions}=this.props;
document.addEventListener(“keydown”,function()){
actions.eventuallyGetAsync(事件,gridAppState.date);
});
}
render(){
const{gridAppState,actions}=this.props;
返回(
);
}
}
App.propTypes={
操作:需要PropTypes.object.isRequired,
gridAppState:PropTypes.object.isRequired
};
函数MapStateTops(状态){
返回{
gridAppState:state.gridAppState
};
}
功能图DispatchToprops(调度){
返回{
操作:bindActionCreators(GridActions、dispatch)
};
}
导出默认连接(
MapStateTops,
mapDispatchToProps
)(App);
我已经验证了正确修改的日期对象正在到达减速器-但是gridAppState似乎停留在我加载的初始日期


在依赖于附加事件处理程序和当前应用程序状态的redux中,处理异步逻辑的正确方法是什么?有没有一个正确的方法可以做到这三点

您应该处理组件中的事件,并根据所按下的键调用正确的操作

因此,当您分派一个异步操作时,您可以执行如下操作

export default function getNextPhoto(currentDate) {
  return (dispatch) => {
    const newDate = calculateNewDate(currentDate);

    dispatch(requestNewPhoto(newDate));

    return photosService.getPhotoOfDate(newDate)
    .then((response) => {
      dispatch(newPhotoReceived(response.photoURL);
    });
  };
}
您应该处理组件上的按键事件,并在知道需要获取新照片时发送操作

你的应用程序看起来像

class App extends React.Component {
  componentDidMount() {
    const { gridAppState, actions } = this.props;
    document.addEventListener("keydown", function() {
      if (event.which == 37) {
        actions.getNextPhoto(gridAppState.date);
      } else if (...) {
        actions.getPrevPhoto(gridAppState.date);
      }

      // etc
    });
  }
}

顺便说一句,您仍然缺少更新Redux存储中状态的还原程序。

我认为在哪里处理哪个键绑定并不重要,但我想我可以通过将逻辑转换为事件处理函数来避免向存储发出“NOACTION”操作。我省略了reducer,因为我非常确定它们可以工作——在没有异步逻辑的情况下对它们进行了测试,而且似乎一切都很好。您是否建议我将两个状态更改分解为一个立即发生并更新应用程序状态的日期概念的分派,以及一个只有在执行异步工作后才能解决的分派?我以为动作制作人必须归还POJO…他们确实如此。例如,requesetNewPhoto action creator可以返回
{type:'REQUEST_NEW_PHOTO',photoDate:newDate}
,然后在商店中获得该信息并更新商店。存储当前状态:
{isLoading:false,currentDate:object,photoURL:'http..}
我们调用requestNewPhoto操作,新状态是
{isLoading:true,currentDate:newDate,photoURL:null}
我们调用newPhotoReceived并再次更新存储。当然,每次更新存储时,组件中都会出现一个反映新状态的新呈现。是的,异步操作是在同步操作发生时调度同步操作的操作。因此,
getNextPhoto()
是一个异步操作,它会触发两个同步操作。