Javascript 反应:操作创建者未调用还原程序
我正在action creator中进行异步调用,并使用结果调用reducer,但由于某些原因,我无法理解reducer没有被调用 actions.js(动作和动作创建者) reducers.jsJavascript 反应:操作创建者未调用还原程序,javascript,reactjs,redux,Javascript,Reactjs,Redux,我正在action creator中进行异步调用,并使用结果调用reducer,但由于某些原因,我无法理解reducer没有被调用 actions.js(动作和动作创建者) reducers.js import { GET_FORMS } from '../actions/actions' export default function formAction(state = {forms:[]}, action) { console.log("received action"+action
import { GET_FORMS } from '../actions/actions'
export default function formAction(state = {forms:[]}, action) {
console.log("received action"+action.type)
switch (action.type) {
case GET_FORMS:
console.log("Action:"+action);
return Object.assign({},state,{
forms:action.formlist
})
default:
return state
}
}
App.js
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom';
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import auth from '../auth'
import FormTable from '../components/FormTable'
import * as FormActions from '../actions/actions'
class App extends Component {
constructor(props) {
super(props);
this.state = {forms: []};
}
componentDidMount() {
// for some reason if i write this.props.actions.getForms () i get an error
// Uncaught Error: Actions must be plain objects. Use custom middleware for
// async actions.
FormActions.getForms();
}
render() {
const {forms,actions} = this.props
console.log(forms);
return (
<FormTable results={forms} actions = {actions} />
)
}
}
App.PropTypes = {
forms: PropTypes.array.isRequired
}
function mapStateToProps() {
const {
forms:forms
} = {forms:[]}
return {
forms
}
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(FormActions, dispatch)
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(App)
import React,{Component,PropTypes}来自“React”
从“react dom”导入react dom;
从“redux”导入{bindActionCreators}
从“react redux”导入{connect}
从“../auth”导入身份验证
从“../components/FormTable”导入FormTable
从“../actions/actions”导入*作为动作
类应用程序扩展组件{
建造师(道具){
超级(道具);
this.state={forms:[]};
}
componentDidMount(){
//出于某种原因,如果我写这个.props.actions.getForms(),我会得到一个错误
//未捕获错误:操作必须是普通对象。请使用自定义中间件
//异步操作。
getForms();
}
render(){
const{forms,actions}=this.props
控制台日志(表格);
返回(
)
}
}
App.PropTypes={
表格:PropTypes.array.isRequired
}
函数mapStateToProps(){
常数{
表格:表格
}={forms:[]}
返回{
形式
}
}
功能图DispatchToprops(调度){
返回{
动作:bindActionCreators(动作、调度)
}
}
导出默认连接(
MapStateTops,
mapDispatchToProps
)(应用程序)
您应该使用redux thunk中间件:
本质上,正如您的代码所示——您没有返回符合FSA的操作(实际上现在也没有返回任何内容)。您需要点击发送,然后返回承诺的结果
有关异步操作创建者的更多信息,请参见此处:这里有一些内容
$.get
不会返回操作,因此将其映射到调度
是无效的
合理地说,这可能会导致对如何从异步操作创建者返回操作的困惑。由于它是异步的,本质上它不能返回最终结果(除非您使用的是es7async
wait
)。您尝试的模式与此相同:
class App extends Component {
...
componentDidMount() {
// Instead of calling getForms, do the same directly
$.get(url, function(res) {
return { type: GET_FORMS, forms: res };
});
}
render() { ... }
}
从$.get
api我们知道$.get
返回一个
,而不是任何行动。因此,您必须在回调中使用结果本身——您不能只返回它。下面是componentDidMount
的示例(注意回调绑定到this
):
redux-thunk
。使用redux thunk
,只需返回一个接受dispatch
作为参数的函数。在本例中,您的操作创建者如下所示:
export function getForms() {
return function(dispatch) {
$.get(url, function(result) {
dispatch({ type: GET_FORMS, forms: result });
})
}
}
这与您已经在做的非常相似,只是您正在创建一个thunk
——它只是一个定义了另一个函数以便以后执行的函数——而不是现在实际执行异步操作,而是定义它以便以后执行componentDidMount
中,您正在调用已导入的操作创建者,但没有调用dispatch
。不过,你有50%的成功率,因为你将动作创建者传递给了connect
,但即使你这样做了,你也没有调用connect
传递给prop的绑定动作创建者——你调用了未绑定的
因此,您需要调用this.props.actions.FormActions()
,而不是调用FormActions.getForms()
。前者不受约束,但后者受约束。调用后者与执行this.props.dispatch(FormActions.getForms())
相同mapDispatchToProps
。您可以将对象传递给connect
的参数。见下文:
// Instead of this
export default connect(mapStateToProps, mapDispatchToProps)(App);
// do this:
export default connect(mapStateToProps, FormActions)(App);
// creates the bound action creator 'this.props.getForms()'
这主要是一种样式选择,但我认为这是一种很好的模式:)对于多个action creator源对象,您可以这样做:
export default connect(mapStateToProps, { ...FormActions, ...UserActions })(App);
感谢对redux流如何工作的详细解释,我能够从action creator获取reducer捕获操作,并使用记录器验证是否存在状态更改。但是在App.js的render方法中,表单数组/对象似乎仍然是空的。我是否在mapstatetoprops中出错。是-mapstatetoprops将始终返回空数组。您正在使用解构赋值,所以常量{forms:forms}={forms:[]};将始终是forms=[]。如果使用connect,则需要指定要注入组件的全局状态的哪一部分。您可以在这里阅读有关react用法的更多信息:是的。我发现我没有将表单映射到状态,因此无法获得更改。该链接帮助我将我的状态映射到表单,并在我的渲染方法中显示和获取数据。谢谢!这个解释非常好,非常有用。从文档中学习是一回事,但通过深思熟虑地回顾某人的尝试来学习是另一回事。。。我很感激你不带偏见、乐于助人的语气。真正地这篇帖子把我从“嗯?”带到了“r e d u x w o r k i n g”(是的)
// Instead of this
export default connect(mapStateToProps, mapDispatchToProps)(App);
// do this:
export default connect(mapStateToProps, FormActions)(App);
// creates the bound action creator 'this.props.getForms()'
export default connect(mapStateToProps, { ...FormActions, ...UserActions })(App);