【问题标题】:I can't fetch the data from reducer to component我无法将数据从减速器获取到组件
【发布时间】:2020-08-20 14:50:54
【问题描述】:

我正在尝试将数据从 reducer 传递到组件并作为 props 接收。

但是数据返回 UNDEFİNED,所以我尝试在 reducer 和 action 上控制台数据,但没关系。来自 API 的数据没有任何问题,但它总是返回到未定义的组件。我的错在哪里?

动作

export default ProfileTab;

import axios from 'axios';
import { BASE, API_KEY } from '../config/env';
export const FETCHED_MOVIES = 'FETCHED_MOVIES';

export function fetchMovies() {
  return (dispatch) => {
    axios
      .get(`${BASE}s=pokemon&apikey=${API_KEY}`)
      .then((result) => result.data)
      .then((data) =>
        dispatch({
          type: FETCHED_MOVIES,
          payload: data.Search,
        }),
      );
  };
}

减速机

import { FETCHED_MOVIES } from '../actions/movies';

const initialState = {
  fetching: false,
  fetched: false,
  movies: [],
  error: {},
};

export default (state = initialState, action) => {
  switch (action.type) {
    case 'FETCHED_MOVIES':
      return {
        ...state,
        movies: action.payload,
      };
    default:
      return state;
  }
};

组件

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

import { fetchMovies } from '../../actions/movies';

class Case extends Component {
  static propTypes = {
    movies: PropTypes.object.isRequired,
  };

  constructor(props) {
    super(props);
  }

  componentDidMount() {
    this.props.fetchMovies();
  }

  onChangeHandler = (e) => {
    this.setState({
      input: e.target.value,
    });
  };

  render() {
    console.log(this.props.movies);

    return (
      <div>
        <div className="movies-root">
          <div className="movies-wrapper">
            <div className="movies-container safe-area">
              <h1>mert</h1>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

const mapStateToProps = (state) => {
  return {
    movies: state.movies,
  };
};

const mapDispatchToProps = {
  fetchMovies,
};

export default connect(mapStateToProps, mapDispatchToProps)(Case);

【问题讨论】:

标签: javascript reactjs redux action


【解决方案1】:

在连接语句中执行此操作:

export default connect(mapStateToProps,{fetchMovies})(Case);

并从您的代码中删除 mapDispatchToProps 函数。

将 props 作为对象分发是非常不正确的。试试这个,它应该可以工作。

【讨论】:

  • 当我编辑 mapStateToProps 时,我可以得到数据 thnx !电影:state.movi​​esReducer.movi​​es
【解决方案2】:

那是因为你的 mapDispatchToProps 函数应该返回一个对象并将 dispatch 作为参数。返回对象中的每个字段都应包含一个调度您的操作的函数。

所以试试这样的:

const mapDispatchToProps = dispatch => {
  return {
    fetchMovies: () => dispatch(fetchMovies())
  }
}

【讨论】:

    【解决方案3】:

    虽然已经有an accepted answer,但我不确定它有多正确,因为通过mapDispatchToProps 完全有效,就像你使用最新的react (16.13.1) 和react-redux (7.2 .1) 版本(我不确定早期版本)。

    现在,假设您的问题包含整个代码,那么缺少两件重要的事情:

    1. 创建商店:

      import { createStore } from "redux";
      const store = createStore(reducer);
      

      并将其传递给Provider 组件:

      <Provider store={store}>
      
    2. 如果您继续按上述操作,您将看到this.props.fetchMovies 发出以下错误:

      动作必须是普通对象。使用自定义中间件进行异步操作。

      要修复它,按照它说的做并添加一个中间件,例如thunk:

      import { createStore, applyMiddleware } from "redux";
      import thunk from "redux-thunk";
      const store = createStore(rootReducer, applyMiddleware(thunk));
      

    下面是完整的代码。请注意,我将fetchMovies“拆分”为两个函数:同步和异步,以说明两者之间的不同用法。为了这个答案的可读性,我还修改了你的代码(主要是更短)。你也可以see a live demo here:

    文件 app.js

    import React, { Component } from "react";
    import { connect } from "react-redux";
    import { fetchMoviesSync, fetchMoviesAsyncMock } from "./api";
    
    class App extends Component {
      componentDidMount() {
        this.props.fetchMoviesSync();
        this.props.fetchMoviesAsyncMock();
      }
      render() {
        return (
          <div>
            <div className="movies-root">
              <div className="movies-wrapper">
                <div className="movies-container safe-area">
                  {this.props.movies.join("\n")}
                </div>
              </div>
            </div>
          </div>
        );
      }
    }
    
    const mapStateToProps = (state) => ({ movies: state.movies });
    const mapDispatchToProps = {
      fetchMoviesSync,
      fetchMoviesAsyncMock
    };
    
    export default connect(mapStateToProps, mapDispatchToProps)(App);
    

    文件 api.js

    export const FETCHED_MOVIES = "FETCHED_MOVIES";
    
    export const fetchMoviesSync = () => ({
      type: FETCHED_MOVIES,
      payload: ["movie1", "movie2", "movie3", "movie4"]
    });
    export const fetchMoviesAsyncMock = () => (dispatch) => {
      dispatch({
        type: FETCHED_MOVIES,
        payload: ["movie5", "movie6", "movie7", "movie8"]
      });
    };
    

    文件 reducer.js

    const initialState = {
      movies: [],
    };
    
    export default (state = initialState, action) => {
      switch (action.type) {
        case "FETCHED_MOVIES":
          return {
            ...state,
            movies: state.movies.concat(action.payload)
          };
        default:
          return state;
      }
    };
    

    文件 index.js

    import React from "react";
    import ReactDOM from "react-dom";
    import Case from "./app";
    import reducer from "./reducer";
    import { createStore, applyMiddleware } from "redux";
    import { Provider } from "react-redux";
    import thunk from "redux-thunk";
    
    let store = createStore(reducer, applyMiddleware(thunk));
    ReactDOM.render(
      <Provider store={store}>
        <Case />
      </Provider>,
      document.getElementById("container")
    );
    

    文件index.html

    <body>
      <div id="container"></div>
    </body>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-04
      • 1970-01-01
      • 1970-01-01
      • 2020-01-16
      • 2018-11-24
      • 2020-04-21
      • 1970-01-01
      相关资源
      最近更新 更多