Kum*_*r R 3 javascript reactjs redux
我正在我的动作创建者中进行异步调用并使用结果调用我的reducer,但由于某种原因我无法理解减速器没有被调用.
actions.js(动作和动作创建者)
export const GET_FORMS = 'GET_FORMS'
export function getForms() {
$.get("server url", function(result) {
return {
type: GET_FORMS,
formlist: result.data.forms
}
})
}
Run Code Online (Sandbox Code Playgroud)
reducers.js
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
}
}
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
Nat*_*gen 12
这里有一些事情.
您的动作创建者不会返回它正在创建的动作.$.get不返回动作,因此将其映射到dispatch不高效.
合理地,这可能会导致对如何从异步动作创建者返回动作感到困惑.由于它是异步的,因此它无法返回最终结果(除非你使用的是es7 async await).您尝试的模式与此相同:
class App extends Component {
...
componentDidMount() {
// Instead of calling getForms, do the same directly
$.get(url, function(res) {
return { type: GET_FORMS, forms: res };
});
}
render() { ... }
}
Run Code Online (Sandbox Code Playgroud)
从$.getapi我们知道$.get返回一个jqXHR对象
,而不是任何一种动作.所以你必须在自己的回调中使用结果 - 你不能只返回它.这是一个componentDidMount可能看起来像什么的例子(注意回调绑定this):
componentDidMount() {
$.get(url, function(res) {
this.props.dispatch({ type: GET_FORMS, forms: res });
}.bind(this))
}
Run Code Online (Sandbox Code Playgroud)在组件或操作创建器中执行异步操作是反模式的,或者至少是不鼓励的.在这种情况下,您将在动作创建者中定义异步,这很棒.但是你也在执行异步操作,这很糟糕.相反,您应该使用某种中间件来处理异步操作.中间件只是在发送后采取行动并对其进行处理的功能,而最常见的是用于此目的redux-thunk.使用redux-thunk,您只需返回一个接受dispatch作为参数的函数.在这种情况下,您的动作创建者将如下所示:
export function getForms() {
return function(dispatch) {
$.get(url, function(result) {
dispatch({ type: GET_FORMS, forms: result });
})
}
}
Run Code Online (Sandbox Code Playgroud)
这与你正在做的非常类似,除了你正在创建一个 - thunk这只是一个定义另一个函数以便稍后执行的函数 - 而不是现在实际执行异步操作,你要为它定义它执行后来.
你实际上并没有派遣任何东西.
要修复的最简单的问题,但绝对是一个障碍:)在componentDidMount,你正在调用你导入的动作创建者,但你没有打电话dispatch.你有50%的路在那里,因为你通过了动作创建者connect,但即使你这样做了,你也没有调用connect进入道具的绑定动作创建者- 你称之为未绑定的动作创建者.
所以FormActions.getForms()不需要打电话,你需要打电话this.props.actions.formActions().前者不受约束,后者则受约束.调用后者与做同样的事情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()'
Run Code Online (Sandbox Code Playgroud)
这个主要是一个样式选择,但我认为这是一个很好的模式:)对于多个动作创建者源对象,你可以这样做:
export default connect(mapStateToProps, { ...FormActions, ...UserActions })(App);
Run Code Online (Sandbox Code Playgroud)