首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React & Redux:无限滚动导致TypeError:调度不是函数错误

React & Redux:无限滚动导致TypeError:调度不是函数错误
EN

Stack Overflow用户
提问于 2020-11-11 07:41:47
回答 2查看 142关注 0票数 0

当用户不断滚动(无限滚动)时,我使用react-infinite-scroll-component包作为加载数据的一种方式。然而,当我用Redux和所有东西设置它时,如果我滚动到底部,我的操作方法会得到以下错误:

代码语言:javascript
复制
TypeError: dispatch is not a function

以下是我用于复制或更多上下文的文件:

TopRatedComponent.js:

代码语言:javascript
复制
import React, { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import { connect } from "react-redux";
import { fetchTopRatedMovies } from '../actions/topRatedAction.js';
import { Container, Row, Col, Button } from 'react-bootstrap';
import { useDispatch } from "react-redux";
import InfiniteScroll from "react-infinite-scroll-component";

const TopRatedComponent = (props) => {
    const dispatch = useDispatch();
    
    let [page, setPage] = useState(3);

    useEffect(() => {
        dispatch(fetchTopRatedMovies(page));
        setPage = page++;
    }, [])

    const { 
        topRatedMovies,
        loading,
        error
     } = useSelector(state => state.topRatedMovies);
 
    
    return (
        <div >
        {loading && <div>LOADING...</div>}
        {error && <div>{error}</div>}

        <Container className="p-4"  >
        <InfiniteScroll
          dataLength={20}
          next={fetchTopRatedMovies(page)}
          hasMore={true}
          loader={<h4>Loading...</h4>}
        >
              {topRatedMovies.results && topRatedMovies.results.map(topRated => (
            <div key={topRated.id}>
              div - #{topRated.title}
            </div>
          ))}
        </InfiniteScroll>
        </Container>

    </div>
    )
};



const mapStateToProps = state => {
    const { topRatedMovies, loading, error } = state.topRatedMovies;
    return {
        topRatedMovies,
        loading,
        error
    };
};

export default connect(
    mapStateToProps,
    {
        fetchTopRatedMovies
    }
)(TopRatedComponent);

store.js:

代码语言:javascript
复制
import { createStore, compose, applyMiddleware, combineReducers } from "redux";
import thunkMiddleware from 'redux-thunk'
import topRatedReducer from '../reducers/topRatedReducer'

  const rootReducer = combineReducers({
    topRatedMovies: topRatedReducer
  });

  const store = createStore(rootReducer,  compose(applyMiddleware(thunkMiddleware),
  ));
  
  export default store;

topRatedAction.js:

代码语言:javascript
复制
import {
  FETCH_TOPRATED_START,
  FETCH_TOPRATED_FAILURE,
  FETCH_TOPRATED_SUCCESS 
} from './actionTypes'
import axios from "axios";


const API_KEY = 'MyAPIKEY';
export  const fetchTopRatedMovies = (page) => {
   // page = 1;
    const API_URL = `https://api.themoviedb.org/3/movie/top_rated?api_key=${API_KEY}&language=en-US&page=` + page;
    return dispatch => {
        dispatch(fetchTopRatedStarted());
        axios.get(API_URL)
        .then(response => {
            dispatch(fetchTopRatedSucceeded(response.data));
        })
        .catch(error =>{
            dispatch(fetchTopRatedFailed(error.message));
        });
    };
};



const fetchTopRatedStarted = () => {
  return{
      type: FETCH_TOPRATED_START,
      payload: {
          isLoading: true
      }
  };
};

const fetchTopRatedSucceeded = topRatedMovies => {
    return{
        type: FETCH_TOPRATED_SUCCESS,
        payload: {
            topRatedMovies
        }
    };
};

const fetchTopRatedFailed = error => {
    return{
        type: FETCH_TOPRATED_FAILURE,
        payload: {
            error
        }
    };
};

topRatedReducer.js

代码语言:javascript
复制
import {
    FETCH_TOPRATED_START,
    FETCH_TOPRATED_FAILURE,
    FETCH_TOPRATED_SUCCESS 
  } from '../actions/actionTypes'

  const initialState = {
      topRatedMovies: [],
      loading: false,
      error: null
  }



  export default function (state = initialState, action){

    switch (action.type) {
        case FETCH_TOPRATED_START:
            return{
                ...state,
                loading: true
            };
        case FETCH_TOPRATED_FAILURE:
            return{
                ...state,
                loading: false,
                error: action.payload.error
            }
        case FETCH_TOPRATED_SUCCESS:
            return{
                ...state,
                loading:false,
                topRatedMovies: action.payload.topRatedMovies
            };
        default:
            return state
    }

  }
EN

回答 2

Stack Overflow用户

发布于 2021-03-18 00:57:07

代码语言:javascript
复制
const infinite = () => {
  dispatch(fetchTopRatedMovies(page));
  setPage=page++;
};

然后从next调用infinite

Next={无限}

票数 1
EN

Stack Overflow用户

发布于 2021-03-18 02:04:13

由于您正在使用connect并将调度传递给mapDispatchToProps,因此您可以简单地使用props中的调度函数,而不是在导入的函数上调用fetchTopRatedMovies

另外,InfiniteScroll的下一个道具不应该直接使用fetchTopRatedMovies,而是从道具中使用,因为它将是被调度的函数实例。

代码语言:javascript
复制
const TopRatedComponent = (props) => {
    
    let [page, setPage] = useState(3);

    useEffect(() => {
        props.fetchTopRatedMovies(page);
        setPage(page => page+1); // call setPage function
    }, [])

    const { 
        topRatedMovies,
        loading,
        error
     } = props
    const fetchData = () => {
        props.fetchTopRatedMovies(page);
        setPage(page => page + 1);
    }
    
    return (
        <div >
        {loading && <div>LOADING...</div>}
        {error && <div>{error}</div>}

        <Container className="p-4"  >
        <InfiniteScroll
          dataLength={20}
          next={fetchData}
          hasMore={true}
          loader={<h4>Loading...</h4>}
        >
              {topRatedMovies.results && topRatedMovies.results.map(topRated => (
            <div key={topRated.id}>
              div - #{topRated.title}
            </div>
          ))}
        </InfiniteScroll>
        </Container>

    </div>
    )
};

const mapStateToProps = state => {
    const { topRatedMovies, loading, error } = state.topRatedMovies;
    return {
        topRatedMovies,
        loading,
        error
    };
};

export default connect(
    mapStateToProps,
    {
        fetchTopRatedMovies
    }
)(TopRatedComponent);

代码语言:javascript
复制
import React, { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import { connect } from "react-redux";
import { fetchTopRatedMovies } from '../actions/topRatedAction.js';
import { Container, Row, Col, Button } from 'react-bootstrap';
import { useDispatch } from "react-redux";
import InfiniteScroll from "react-infinite-scroll-component";

const TopRatedComponent = (props) => {
    const dispatch = useDispatch();
    
    let [page, setPage] = useState(3);

    useEffect(() => {
        dispatch(fetchTopRatedMovies(page));
        setPage(page => page+1); // call setPage function
    }, [])

    const { 
        topRatedMovies,
        loading,
        error
     } = useSelector(state => state.topRatedMovies);
 
    const fetchData = () => {
        dispatch(fetchTopRatedMovies(page));
        setPage(page => page + 1);
    }
    return (
        <div >
        {loading && <div>LOADING...</div>}
        {error && <div>{error}</div>}

        <Container className="p-4"  >
        <InfiniteScroll
          dataLength={20}
          next={fetchData}
          hasMore={true}
          loader={<h4>Loading...</h4>}
        >
              {topRatedMovies.results && topRatedMovies.results.map(topRated => (
            <div key={topRated.id}>
              div - #{topRated.title}
            </div>
          ))}
        </InfiniteScroll>
        </Container>

    </div>
    )
};

export default TopRatedComponent; // Note that we are not using connect here

P.S.请注意,您不需要像useSelector和useDispatch那样同时使用连接和挂钩,您可以使用它们中的任何一个。遵循上述方法中的任何一种都可以为您工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64778420

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档