Как работать с API-вызовом Action в Redux? - PullRequest
0 голосов
/ 14 мая 2019

Я новичок в Redux и пытаюсь заставить его работать с моим приложением, но у меня проблемы с пониманием, как работать с асинхронными действиями в нем.У меня есть действие, это вызов API.Это действие должно быть вызвано, как только мое другое состояние не будет пустым.Я не получаю никаких ошибок, но не думаю, что мое действие вызвано, так как данные пусты.Кто-нибудь может помочь понять, что я делаю не так?

Вот мой Actions.js.WordsFetchData - это действие, которое мне нужно вызвать:

 export function wordsFetchDataSuccess(items){
    return{
        type: 'WORDS_FETCH_DATA_SUCCESS',
        items
    };
 }

 export function wordsAreFetching(bool){
     return{
        type: 'WORDS_ARE_FETCHING',
        areFetching: bool
     }
 }

 export function wordsHasErrored(bool) {
     return {
        type: 'WORDS_HAS_ERRORED',
        hasErrored: bool
     };
 }

 export function wordsFetchData(parsed) {
    return (dispatch) => {
        dispatch(wordsAreFetching(true));

        fetch('URL', {
            method: "POST",
            headers: {
                "Content-type": "application/json"
            },body: JSON.stringify({
                 words: parsed
        })
    })
        .then((response) => {
            if (!response.ok) {
                throw Error(response.statusText);
            }

            dispatch(wordsAreFetching(false));

            return response;
        })
        .then((response) => response.json())
        .then((items) => dispatch(wordsFetchDataSuccess(items)))
        .catch(() => dispatch(wordsHasErrored(true)));
    };
 }

Вот мои редукторы:

export function word(state = [], action) {
switch (action.type) {
    case 'WORDS_FETCH_DATA_SUCCESS':
        return action.items;

    default:
        return state;
    }
}

export function wordsAreFetching(state = false, action) {
    switch (action.type) {
        case 'WORDS_ARE_FETCHING':
            return action.areFetching;

        default:
            return state;
    }
}

export function wordsFetchHasErrored(state = false, action) {
    switch (action.type) {
        case 'WORDS_HAS_ERRORED':
           return action.hasErrored;

    default:
        return state;

    }

 }

Это моя функция componentDidMount:

componentDidMount = (state) => {
    this.props.fetchData(state);
};

Этофункция, после завершения которой должно быть вызвано действие:

 parseInput = async () => {
    console.log(this.state.textInput);
    let tempArray = this.state.textInput.split(" "); // `convert 
    string into array`
    let newArray = tempArray.filter(word => word.endsWith("*"));
    let filterArray  = newArray.map(word => word.replace('*', ''));
    await this.setState({filterArray: filterArray});
    await this.props.updateData(this.state.filterArray);
    if (this.state.projectID === "" && this.state.entity === "")
        this.dialog.current.handleClickOpen();
    else
        if (this.state.filterArray.length !== 0)
            this.componentDidMount(this.state.filterArray);
    };

Это функции mapStateToProps и mapDispatchToProps.

const mapStateToProps = (state) => {
    return {
        items: state.items,
        hasErrored: state.wordsFetchHasErrored,
        areFetching: state.wordsAreFetching
    };
};

const mapDispatchToProps = (dispatch) => {
    return {
        fetchData: wordsFetchData
    };
};

Ответы [ 2 ]

0 голосов
/ 14 мая 2019

Пара вещей:

  1. Нет необходимости передавать состояние в componentDidMount, ваш mapDispatchToProps не использует его.

  2. Вот предложение структурировать эти функции. Они более лаконичны и читабельны.

const mapStateToProps = ({items, wordsAreFetching, wordsFetchHasError}) => ({
   items,
   hasErrored: wordsFetchHasErrored,
   areFetching: wordsAreFetching,
});

const mapDispatchToProps = () => ({
   fetchData: wordsFetchData(),
});

Другие заметки и полезные вещи: Если вы используете thunk, у вас будет доступ ко всему вашему хранилищу в качестве второго аргумента. Например:

    return (dispatch, getState) => {
        dispatch(wordsAreFetching(true));
        console.log('getState', getState());
       const { words } = getState().items;
// This is a great place to do some checks to see if you _need_ to fetch any data!
// Maybe you already have it in your state?

     if (!words.length) {
        fetch('URL', {
            method: "POST",
            headers: {
                ......
      }

    })

Надеюсь, это поможет, если вам нужно что-то еще, не стесняйтесь спрашивать.

0 голосов
/ 14 мая 2019

Для выполнения выборки требуется только одно действие (т. Е. WORDS_ARE_FETCHING), остальные случаи (т. Е. WORDS_HAS_ERRORED & WORDS_FETCH_DATA_SUCCESS) могут обрабатываться внутри вашего редуктора.

Ваше действие:

 export function wordsAreFetching(){
     return{
        type: 'WORDS_ARE_FETCHING',
     }
 }

Ваш новый редуктор:

export function word(state = [], action) {
switch (action.type) {
    case 'WORDS_ARE_FETCHING':
        return {...state, error: false, areFetching: true};
    case 'WORDS_FETCH_DATA_SUCCESS':
        return {...state, items: action.payload , areFetching: false};
    case 'WORDS_HAS_ERRORED':
        return {...state, error: true, areFetching: false};
    default:
        return state;
}

Затем вы можете вызвать WORDS_FETCH_DATA_SUCCESS после получения данных отсюда:

export function wordsFetchData() {
    try {
        const response = await axios.get(YOUR_URL);
        return dispatch({ type: WORDS_FETCH_DATA_SUCCESS, payload: response.data });
    } catch (err) {
        return dispatch({ type: WORDS_HAS_ERRORED });
    }
 }

Посмотрите на этот пример , в нем используются аксиосы, которые могут помочь вам с асинхронными вызовами.

...