我无法从 reducer 获取数据到组件
I can't fetch the data from reducer to component
我正在尝试将数据从 reducer 传递到组件并作为 props 接收。
但是数据 return 未定义,所以我尝试控制 reducer 和 action 上的数据,但没问题。来自 API 的数据没有任何问题,但它总是 return 组件未定义。我的错在哪里?
动作
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);
那是因为您的 mapDispatchToProps 函数应该 return 一个对象并以 dispatch 作为参数。 returned 对象中的每个字段都应包含一个调度您的操作的函数。
所以尝试这样的事情:
const mapDispatchToProps = dispatch => {
return {
fetchMovies: () => dispatch(fetchMovies())
}
}
在连接语句中这样做:
export default connect(mapStateToProps,{fetchMovies})(Case);
并从您的代码中删除 mapDispatchToProps
函数。
将 props 作为一个对象来分发是非常不正确的。试试这个,它应该可以工作。
尽管已经有 ,但我不确定它的正确性如何,因为按照您对最新 react
(16.13. 1) 和 react-redux
(7.2.1) 版本(我不确定早期版本)。
现在,假设您的问题包含整个代码,则缺少两件重要的事情:
正在创建商店:
import { createStore } from "redux";
const store = createStore(reducer);
并将其传递给 Provider
组件:
<Provider store={store}>
如果继续按上述操作,您会看到 this.props.fetchMovies
发出以下错误:
Actions must be plain objects. Use custom middleware for async actions.
要修复它,按照它说的去做并添加一个中间件,例如thunk
:
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
const store = createStore(rootReducer, applyMiddleware(thunk));
下面是完整代码。请注意,我将 fetchMovies
“拆分”为两个函数:sync 和 async,以说明两者之间的区别用法。为了这个答案的可读性,我还修改了您的代码(主要是更短)。您也可以 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>
我正在尝试将数据从 reducer 传递到组件并作为 props 接收。
但是数据 return 未定义,所以我尝试控制 reducer 和 action 上的数据,但没问题。来自 API 的数据没有任何问题,但它总是 return 组件未定义。我的错在哪里?
动作
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);
那是因为您的 mapDispatchToProps 函数应该 return 一个对象并以 dispatch 作为参数。 returned 对象中的每个字段都应包含一个调度您的操作的函数。
所以尝试这样的事情:
const mapDispatchToProps = dispatch => {
return {
fetchMovies: () => dispatch(fetchMovies())
}
}
在连接语句中这样做:
export default connect(mapStateToProps,{fetchMovies})(Case);
并从您的代码中删除 mapDispatchToProps
函数。
将 props 作为一个对象来分发是非常不正确的。试试这个,它应该可以工作。
尽管已经有 react
(16.13. 1) 和 react-redux
(7.2.1) 版本(我不确定早期版本)。
现在,假设您的问题包含整个代码,则缺少两件重要的事情:
正在创建商店:
import { createStore } from "redux"; const store = createStore(reducer);
并将其传递给
Provider
组件:<Provider store={store}>
如果继续按上述操作,您会看到
this.props.fetchMovies
发出以下错误:Actions must be plain objects. Use custom middleware for async actions.
要修复它,按照它说的去做并添加一个中间件,例如
thunk
:import { createStore, applyMiddleware } from "redux"; import thunk from "redux-thunk"; const store = createStore(rootReducer, applyMiddleware(thunk));
下面是完整代码。请注意,我将 fetchMovies
“拆分”为两个函数:sync 和 async,以说明两者之间的区别用法。为了这个答案的可读性,我还修改了您的代码(主要是更短)。您也可以 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>