redux 在函数组件React中调用fetch函数

p8h8hvxi  于 2023-06-06  发布在  React
关注(0)|答案(1)|浏览(128)

我已经尝试了很多方法来在渲染之前只获取一次数据,但我仍然有一些问题:
1.我不能在componentDidMount中调用分派,因为有一个规则,我只能在Functional组件中这样做。
1.如果我尝试在Functional组件的开头调用fetch函数,它会开始无限地重新渲染,因为fetch函数每次都会调用并更改Redux存储中的状态。
1.我找到了一个解决方案useEffect,但它生成了一个异常"Invalid hook call",就像第一点一样。
如何在此组件中只调用一次fetch函数?
以下是我的component

import React, { useEffect } from "react";
import { useParams as params} from "react-router-dom";
import { VolunteerCardList } from "./VolunteerCardList";
import { AnimalNeeds } from "./AnimalNeeds";
import { AppState } from "../reducers/rootReducer";
import { connect } from "react-redux";
import { Page404 } from "./404";
import { fetchAnimal } from "../actions/animalAction";
import { Dispatch } from "redux";
import { IAnimalCard } from "../interfaces/Interfaces";

const AnimalCard: React.FC<Props> = ({animal, loading, fetch}) => {
    useEffect(() => {   
            fetch(); //invalid hook call????
    }, [])
    
    
    return (
        <div className="container">
            some HTML
        </div>
    )
}

interface RouteParams {
    shelterid: string,
    animalid: string,
}

interface mapStateToPropsType {
    animal: IAnimalCard,
    loading: boolean
}

const mapStateToProps = (state: AppState) : mapStateToPropsType=> {
    return{
        animal: state.animals.animal,
        loading: state.app.loading
    }
}

interface mapDispatchToPropsType {
    fetch: () => void;
}

const mapDispatchToProps = (dispatch: Dispatch<any>) : mapDispatchToPropsType => ({
    fetch : () => {
        const route = params<RouteParams>();
        dispatch(fetchAnimal(route.shelterid, route.animalid));
    }
})

type Props  = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>;

export default connect(mapStateToProps, mapDispatchToProps as any)(AnimalCard);

这是我的reducer

export const animalReducer = (state: AnimalReducerType = initState, action: IAction) => {

switch (action.type) {
    case AnimalTypes.FETCH_ANIMAL:
            return {...state, animal: action.payload};
        break;

    default:
        return state;
        break;
}

这就是行动:

export interface IFetchAnimalAction  {
    type: AnimalTypes.FETCH_ANIMAL,
    payload: IAnimalCard
}

export type IAction = IFetchAnimalAction;

export const fetchAnimal = (shelterId : string, animalId: string) => {
    return async (dispatch: Dispatch)  => {
        const response = await fetch(`https://localhost:44300/api/animals/${animalId}`);
        const json = await response.json();
        dispatch<IFetchAnimalAction>({type: AnimalTypes.FETCH_ANIMAL, payload: json})
    }
}
dba5bblo

dba5bblo1#

这将作为旧的生命周期方法componentDidMount运行:

useEffect(() => {   
  fetch(); //invalid hook call????
}, [])

我猜您想要复制的行为是componentWillMount迭代的行为,这是任何标准钩子都无法做到的。我的解决方案是让获取一些loadingState,最显式的是:

const AnimalCard: React.FC<Props> = ({animal, loading, fetch}) => {
    const [isLoading, setIsLoading] = useState<boolean>(true);

    useEffect(() => {   
      fetch().then(res => {
        // Do whatever with res
        setIsLoading(false);
      } 
    }, [])

    if(isLoading){
      return null
    }

    return (
        <div className="container">
            some html
        </div>
    )
}

相关问题