Вызов функции выборки в функциональном компоненте React - PullRequest
0 голосов
/ 12 апреля 2020

Я пробовал так много способов получить данные только один раз перед рендерингом, но у меня возникла проблема:

1) Я не могу вызвать диспетчеризацию в componentDidMount, потому что есть правило, что я могу это сделать только в функциональном компоненте

2) Если я пытаюсь вызвать функцию выборки в начале функционального компонента, она начинает бесконечно перерисовываться, потому что функция выборки вызывает каждый раз и изменяет состояние в хранилище с избыточностью

3) Я нашел решение с useEffect, но оно генерирует исключение "Invalid hook call", как в первой точке

Как я могу вызвать функцию выборки только один раз в этом компоненте?

вот мой 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})
    }
} 

1 Ответ

0 голосов
/ 12 апреля 2020

Это работает как старый метод жизненного цикла componentDidMount:

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

Я думаю, вы хотите повторить поведение, повторяемое componentWillMount, которое вы не можете сделать ни одним из стандартных перехватчиков. Мое go - решение для этого состоит в том, чтобы позволить некоторому loadingState приобретать, наиболее явно как:

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

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

    if(!isLoading){
      return null
    }

    return (
        <div className="container">
            some html
        </div>
    )
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...