首页 > 解决方案 > React redux api 每 x 秒轮询一次

问题描述

我已经完成了这项工作,但我正在寻求一种更“最佳实践方式”。

它使用https://icanhazdadjoke api 来显示每 x 秒更新一次的随机笑话。有更好的方法吗?

最终我想添加停止、启动、重置功能,感觉这种方式可能不是最好的。

我可以使用任何中间件吗?

Redux 操作

// action types
import axios from 'axios';
export const FETCH_JOKE = 'FETCH_JOKE';
export const FETCH_JOKE_SUCCESS = 'FETCH_JOKE_SUCCESS';
export const FETCH_JOKE_FAILURE = 'FETCH_JOKE_FAILURE';


function fetchJoke() {
  return {
    type: FETCH_JOKE
  };
}

function fetchJokeSuccess(data) {
  return {
    type: FETCH_JOKE_SUCCESS,
    data
  };
}

function fetchJokeFail(error) {
  return {
    type: FETCH_JOKE_FAILURE,
    error
  };
}

export function fetchJokeCall(){
  return function(dispatch){
    dispatch(fetchJoke());
    return axios.get('https://icanhazdadjoke.com', { headers: { 'Accept': 'application/json' }})
    .then(function(result){
      dispatch(fetchJokeSuccess(result.data))
    })
    .catch(error => dispatch(fetchJokeFail(error)));
  }
}

Redux 减速器

import {combineReducers} from 'redux';
import {FETCH_JOKE, FETCH_JOKE_SUCCESS, FETCH_JOKE_FAILURE} from '../actions';

const defaultStateList = {
  isFetching: false,
  items:[],
  error:{}
};

const joke = (state = defaultStateList, action) => {
  switch (action.type){
  case FETCH_JOKE:
    return {...state, isFetching:true};
  case FETCH_JOKE_SUCCESS:
    return {...state, isFetching:false, items:action.data};
  case FETCH_JOKE_FAILURE:
    return {...state, isFetching:false, error:action.data};
  default:
    return state;
  }
};

const rootReducer = combineReducers({
  joke
});

export default rootReducer;

笑话组件

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { fetchJokeCall } from '../actions';


class Joke extends Component {
  componentDidMount() {
    this.timer = setInterval(()=>  this.props.fetchJokeCall(), 1000);
  }
  componentWillUnmount() {
    clearInterval(this.timer)
    this.timer = null;
  }
  render() {
    return (
      <div>
        {this.props.joke.joke}
      </div>
    );
  }
}

Joke.propTypes = {
  fetchJokeCall: PropTypes.func,
  joke: PropTypes.array.isRequired
};

function mapStateToProps(state) {
  return {
    joke: state.joke.items,
    isfetching: state.joke.isFetching
  };
}

export default connect(mapStateToProps, { fetchJokeCall })(Joke);

标签: reactjsreduxpolling

解决方案


Redux-Sagas 更好,我们也在我们的应用程序中使用它,这就是您可以使用 Redux-Sagas 进行轮询的方式

只是为了让您知道这是如何做到的,您还需要了解 Redux-Sagas 的工作原理

行动

export const FETCH_JOKE = 'FETCH_JOKE';
export const FETCH_JOKE_SUCCESS = 'FETCH_JOKE_SUCCESS';
export const FETCH_JOKE_FAILURE = 'FETCH_JOKE_FAILURE';
export const START_POLLING = 'START_POLLING';
export const STOP_POLLING = 'STOP_POLLING';

function startPolling() {
      return {
        type: START_POLLING
      };
    }

function stopPolling() {
      return {
        type: STOP_POLLING
      };
    }

function fetchJoke() {
  return {
    type: FETCH_JOKE
  };
}

function fetchJokeSuccess(data) {
  return {
    type: FETCH_JOKE_SUCCESS,
    data
  };
}

function fetchJokeFail(error) {
  return {
    type: FETCH_JOKE_FAILURE,
    error
  };
}

减速器

import {combineReducers} from 'redux';
import {FETCH_JOKE, FETCH_JOKE_SUCCESS, FETCH_JOKE_FAILURE, START_POLLING, STOP_POLLING } from '../actions';

const defaultStateList = {
  isFetching: false,
  items:[],
  error:{},
  isPolling: false,
};

const joke = (state = defaultStateList, action) => {
  switch (action.type){
  case FETCH_JOKE:
    return {...state, isFetching:true};
  case FETCH_JOKE_SUCCESS:
    return {...state, isFetching:false, items:action.data};
  case FETCH_JOKE_FAILURE:
    return {...state, isFetching:false, error:action.data};
  case START_POLLING:
    return {...state, isPolling: true};
  case STOP_POLLING:
    return {...state, isPolling: false};
  default:
    return state;
  }
};

const rootReducer = combineReducers({
  joke
});

export default rootReducer;

传说

import { call, put, takeEvery, takeLatest, take, race } from 'redux-saga/effects'

import {FETCH_JOKE, FETCH_JOKE_SUCCESS, FETCH_JOKE_FAILURE, START_POLLING, STOP_POLLING } from '../actions';

import axios from 'axios';



function delay(duration) {
  const promise = new Promise(resolve => {
    setTimeout(() => resolve(true), duration)
  })
  return promise
}

function* fetchJokes(action) {
  while (true) {
    try {
      const { data } = yield call(() => axios({ url: ENDPOINT }))
      yield put({ type: FETCH_JOKE_SUCCESS, data: data })
      yield call(delay, 5000)
    } catch (e) {
      yield put({ type: FETCH_JOKE_FAILURE, message: e.message })
    }
  }
}

function* watchPollJokesSaga() {
  while (true) {
    const data = yield take(START_POLLING)
    yield race([call(fetchJokes, data), take(STOP_POLLING)])
  }
}

export default function* root() {
  yield [watchPollJokesSaga()]
}

你也可以使用 Redux-Observable,如果你想了解更多内容,请阅读这篇文章


推荐阅读