Как исправить 'Действия должны быть простыми объектами.Используйте пользовательское промежуточное ПО для асинхронных действий. ' - PullRequest
0 голосов
/ 25 марта 2019

Я делаю компонент React-redux для встраивания в блейд-файл Laravel. Где на стороне реакции,

Я использую избыточность с thunk. Когда я пытаюсь получить данные без thunk из маршрута Laravel, он получается правильно.

Но когда я использую запрос axios в создателе действия, чтобы получить данные асинхронно. Это дает:

'Uncaught Error: Действия должны быть простыми объектами. Используйте пользовательское промежуточное ПО для асинхронных действий. '

Это входной компонент стороны реакции.

Entry.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

import reducer from '../store/reducers/reducer';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';

import thunk from "redux-thunk";


const store = createStore(reducer, applyMiddleware(thunk)
+window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
// console.log(getState());

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

Это App.js основной компонент

import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from 'prop-types';
import axios from 'axios';
import {getCurrentPostLikes} from '../store/actions/actions';

class App extends Component {
    constructor(props) {
        super(props)

        var domain = window.location.hostname;
        var url = window.location.pathname;
        var urlsplit = url.split("/");
        var post_slug = urlsplit[urlsplit.length - 1];

        this.state={
            post_slug: post_slug,
            post_likes:''
        }
    }

    kFormatter(num) {
        return num > 999 ? (num / 1000).toFixed(1) + 'k' : num
    }

    componentDidMount() {
        this.props.getCurrentPostLikes();
        // axios.get(`/api/get_post_likes/${this.state.post_slug}`)
        // .then(response => {
        //     console.log(response.data.likes);
        //     this.setState({
        //         post_likes: response.data.likes
        //     })
        // })
    }

  render() {
    return (
      <div className="App">
        <a href="javascript:"><img src="/images/love.svg" alt="post like" width="50px" height="50px"/></a>
        <p>{this.kFormatter(this.state.post_likes)}</p>
        <p><span>{this.props.likes}</span></p>
      </div>
    );
  }
}


export default connect(null, {getCurrentPostLikes})(App);
// export default connect( mapStateToProps, mapDispachToProps )(App);

Это actions.js файл / store / actions / actions.js

// types.js is also defined properly as
// export const GET_POST_LIKES = 'GET_POST_LIKES';

import axios from 'axios';
import {GET_POST_LIKES} from './types';

// Get current post likes
export const getCurrentPostLikes = () => dispatch => {
  return dispatch => {
    setTimeout(() => {
      axios.get(`/api/get_post_likes/2`)
          .then(res => {
              // console.log(response.data.likes);
              // console.log(getState());
            setTimeout(() => {
                dispatch({
                    type: GET_POST_LIKES,
                    payload: res.data.likes
                })
            }, 4000);
          })
          .catch(err => {
              dispatch({
                  type: GET_POST_LIKES,
                  payload: {}
              })
          })
    }, 3000);
  }
}

Пробовал и этого создателя действия, но все равно та же ошибка

export const getCurrentPostLikes = () => {
  return dispatch => {
      axios.get(`/api/get_post_likes/2`)
          .then(res => {
                dispatch({
                    type: GET_POST_LIKES,
                    payload: res.data.likes
                })
          })
          .catch(err => {
              dispatch({
                  type: GET_POST_LIKES,
                  payload: {}
              })
          })
  }
}

Это файл redurs.js в / store / redurs / reducer.js

import { GET_POST_LIKES } from '../actions/types';

const initialState = {
    likes: null
};

const reducer = (state=initialState, action) => {
    const newState = {...state};

    switch(action.type){
        case 'GET_POST_LIKES':
            return {
                ...state,
                post: action.payload
            }

        case 'LIKE_UP':
            newState.likes += action.value
            break;
    }
    return newState;
};

export default reducer;

Теперь, это должно вернуть значение поля таблицы сообщений, с post id = 2.

Ответы [ 4 ]

2 голосов
/ 25 марта 2019

Это «подпись» карри-функции создателя действия с использованием redux-thunk:

export const getCurrentPostLikes = () => async dispatch => {
  const response = await axios.get(`/api/get_post_likes/2`);
  dispatch({ type: GET_POST_LIKES, payload: response.data.likes });
};
1 голос
/ 25 марта 2019

Ваша проблема в Entry.js, эта строка:

const store = createStore(reducer, applyMiddleware(thunk) +window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()

Вы устанавливаете промежуточное ПО thunk в качестве второго параметра.Второй параметр предназначен для начального состояния. Промежуточное программное обеспечение Thunk должно быть частью составных расширений третьего параметра функции createStore.

Параметры должны применяться следующим образом:

createStore(
  connectRouter(history)(rootReducer),
  initialState,
  composedEnhancers
)

Полный пример:

import { createStore, applyMiddleware, compose } from 'redux'
import { connectRouter, routerMiddleware } from 'connected-react-router'
import thunk from 'redux-thunk'
import createHistory from 'history/createHashHistory'
import rootReducer from './core/reducers'

export const history = createHistory()

const initialState = {}
const enhancers = []
const middleware = [thunk, routerMiddleware(history)]

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

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

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


export default createStore(
  connectRouter(history)(rootReducer),
  initialState,
  composedEnhancers
)
0 голосов
/ 31 марта 2019

Вот как вы хотите, чтобы ваш создатель действий выглядел:

export const getCurrentPosts = () => {
  return async function(dispatch, getState) {
    const response = await axios.get("/api/get_post_likes");
    dispatch({ type: "GET_POST_LIKES", payload: response });
  };
};

Не включайте в него Обещания и используйте синтаксис ES7 async/await, а также пропустите setTimeout, если вы не можете предоставитьдействительно хорошее оправдание для того, чтобы истекло время ожидания асинхронного запроса, который уже занимает ненулевое количество времени для выполнения, может быть, я не понимаю, но вы хотите, чтобы эти данные не так ли?Ваши редукторы должны выполнять свою работу и, в конечном итоге, обновлять состояние в вашем приложении.

То, что у меня есть выше, не идеально в том смысле, что его шаблон, как будто вам на самом деле не нужен getState, не оченьДа, это часть промежуточного программного обеспечения, но если вы не собираетесь использовать что-то, нет необходимости определять это, но в любом случае я пытаюсь привести вас к точке, где ваш создатель действий снова работает, и вы щадите свои глаза и свой разум.

0 голосов
/ 25 марта 2019

Кажется, в вашем действии есть дополнительные dispatch =>

export const getCurrentPostLikes = () => dispatch => {

    setTimeout(() => {
      axios.get(`/api/get_post_likes/2`)
          .then(res => {
              // console.log(response.data.likes);
              // console.log(getState());
            setTimeout(() => {
                dispatch({
                    type: GET_POST_LIKES,
                    payload: res.data.likes
                })
            }, 4000);
          })
          .catch(err => {
              dispatch({
                  type: GET_POST_LIKES,
                  payload: {}
              })
          })
    }, 3000);

}
...