@acorn

Ошибка redux Error: Actions must be plain objects. Use custom middleware for async actions?

привет!
Делаю страницу авторизации. При нажатии на кнопку submit появляется эта ошибка Error: Actions must be plain objects. Use custom middleware for async actions. Использую thunk он есть в коде store.js, но почему эта ошибка возникает??помогите,пожалуйста!!

вот мой action и reducer login
import Promise from 'es6-promise';

// actions
const LOGIN_PENDING = 'LOGIN_PENDING';
const LOGIN_SUCCESS='LOGIN_SUCCESS';
const LOGIN_ERROR='LOGIN_ERROR';

export const loginPending = isLoginPending =>({
        type: LOGIN_PENDING,
        isLoginPending
});
export const loginSuccess = isLoginSuccess =>({
        type: LOGIN_SUCCESS,
        isLoginSuccess
});
export const loginError = isLoginError =>({
        type: LOGIN_ERROR,
        isLoginError
});


//actions which send login request and dispatch actions
export function login (username,password){
    return dispatch => {
        dispatch(loginPending(true));
        dispatch(loginSuccess(false));
        dispatch(loginError(null));
        sendRequestLogin(username, password)
            .then(success =>{
                dispatch(loginPending(false));
                dispatch(loginSuccess(true));
            })
            .catch(err=>{
                dispatch(loginPending(false));
                dispatch(loginError(err));
            });
    }
}
//simulate login request : username,password is admin
function sendRequestLogin (username,password) {
    return new Promise ((resolve, reject)=>{
            if (username === "admin" && password === "admin") {
                return resolve(true)
            } else {
                return reject(new Error('Invalid username or password '))
            }
    });
}
// reducer which change data in reducer store
const loginReducer =(state = {
    isLoginPending: false,
    isLoginSuccess: false,
    isLoginError: null
}, action) =>{
    switch (action.type){
        case LOGIN_PENDING:
            return {
                ...state,
                isLoginPending: action.isLoginPending
            };
        case LOGIN_SUCCESS:
            return{
                ...state,
                isLoginSuccess: action.isLoginSuccess
            };

        case LOGIN_ERROR:
            return {
                ...state,
                isLoginError: action.isLoginError
            };

        default:
            return state;
    }
};
export default loginReducer;

вот мой store
import { createStore, applyMiddleware, compose } from 'redux'
import { routerMiddleware } from 'react-router-redux'
import thunk from 'redux-thunk'
import createHistory from 'history/createBrowserHistory'
import rootReducer from './reducers/rootReducer'

export const history = createHistory()

const initialState = {} // or persisted state.
const enhancers = []
const middleware = [
    thunk,
    routerMiddleware(history)
]


if (process.env.NODE_ENV === 'development') {
    const devToolsExtension = window.devToolsExtension

    if (typeof devToolsExtension === 'function') {
        enhancers.push(devToolsExtension())
    }
}

const composedEnhancers = compose(
    applyMiddleware(...middleware),
    ...enhancers
)

export default createStore(
    rootReducer,
    initialState,
    composedEnhancers
)

вот index.js
import React from 'react';
import ReactDOM from 'react-dom';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import { createStore, applyMiddleware, combineReducers } from 'redux'
import { Provider } from 'react-redux'
import { createLogger } from 'redux-logger'
import thunk from 'redux-thunk'
import './index.css';
import App from './containers/App';
import registerServiceWorker from './registerServiceWorker';
import { loadState, saveState  } from './modules/localStorage'

import { initialize, addTranslation, localeReducer, setActiveLanguage } from 'react-localize-redux';
import { Router, Route, IndexRoute, browserHistory } from 'react-router'
import rootReducer from './reducers/rootReducer'

const translations = require('./global.locale.json');
const languages = ['en', 'fi'];
// ACTION
const RANDOMIZE = 'RANDOMIZE';

const actionRandomize = {
    type: RANDOMIZE,
    text: 'dddd'
};
const маке10 = {
    type: 'МАКЕ10'
};

const actionADDSOMETHING = {
    type: 'ADD_SOMETHING',
    value: {}
};

const addSomething = (thing) => {
    return {
        type: 'ADD_SOMETHING',
        thing
    }
};
// end ACTION
// STATE
const initialState = loadState();
onsole.log(store.getState())

let store = createStore(combineReducers(
    {potato: rootReducer,
        locale: localeReducer}),
    window.STATE_FROM_SERVER)


store.subscribe(() => {
    saveState(store.getState())
})

// Log the initial state
console.log(store.getState())

store.dispatch(actionRandomize);
console.log(store.getState())

store.dispatch(маке10);
console.log(store.getState())

store.dispatch(actionADDSOMETHING);
console.log(store.getState())


store.dispatch(addSomething({"ggg":"00"}));


// const defaultLanguage = storage.getItem('language') || languages[0];
const defaultLanguage = languages[0];

store.dispatch(initialize(languages, { defaultLanguage }));

store.dispatch(addTranslation(translations));

// store.dispatch(setActiveLanguage('en'));



ReactDOM.render(
    <Provider store={store}>
        <MuiThemeProvider>
            <App />
        </MuiThemeProvider>
    </Provider>, document.getElementById('root'));

registerServiceWorker();


вот форма Login.js

//todo translate???
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Link } from 'react-router';
import TextField from 'material-ui/TextField';
import RaisedButton from 'material-ui/RaisedButton';
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
import { connect } from 'react-redux';
import {Redirect} from 'react-router-dom';

import { login } from '../reducers/login-reducer';

class Login extends Component {

    constructor(props) {
        super(props);
        this.state = {
            username:'',
            password:''
        };
        this.onSubmit = this.onSubmit.bind(this);
    };
    render() {
        let { username, password } = this.state,
            { isLoginPending, isLoginSuccess, isLoginError } = this.props;
        return (
                    <div className="form-login" onSubmit={this.onSubmit}>
                    <h1><b>Sisäänkirjautuminen</b></h1>
                    <h3>Kirjaudu sisään antamalla käyttäjätunnus ja salasana.</h3>
                    <form name ="loginForm">
                        <TextField
                            type="text"
                            floatingLabelText="Username"
                            onChange={(e) =>this.setState({username: e.target.value})}
                            value={username}
                            fullWidth={true}
                        />
                        <TextField
                            type="password"
                            floatingLabelText="Password"
                            onChange={(e) =>this.setState({password: e.target.value})}
                            value={password}
                            fullWidth={true}
                        />
                        <br/>
                        <RaisedButton label="Login" type="submit"/>

                        <div className="message">
                            { isLoginPending && <div>Please wait...</div> }
                            { isLoginSuccess && <div>Success</div>}
                            { isLoginError && <div>{ isLoginError.message }</div> }
                        </div>
                    </form>
                </div>
    )}
    onSubmit =(e)=> {
        e.preventDefault();
        let { username, password }=this.state;
        this.props.login(username,password);
        this.setState({
            username: '',
            password: ''
        });
        console.log('click')
    }
}

const mapStateToProps = (state)=>{
 return {
     isLoginPending: state.isLoginPending,
     isLoginSuccess: state.isLoginSuccess,
     isLoginError: state.isLoginError
 };
};
const mapDispatchToProps = (dispatch) => {
    return {
        login: (username, password) => dispatch(login(username,password))
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(Login);
  • Вопрос задан
  • 2692 просмотра
Решения вопроса 1
Вы создаете стор в отдельном файле. Там миддлвар подключается.
Но далее в index.js вы создаете другой стор, где миддлваров уже нет. И в Provider передаете именно его.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы