如何在useReducer中进行api调用?

ln0*_*nv2 1 reactjs react-hooks use-reducer

这是一个类组件,我想使用它重构为功能组件useReducer

export default class FootballMatchesData extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedYear: null,
      matchData: [],
      firstCall: false
    };
  }

  chooseYear = (year) => (e) => {
    this.setState({
      selectedYear: year
    })
    axios.get(`https://website?property=${year}`)
      .then(res => {
        this.setState({ matchData: res.data, firstCall: true })
      })
  }

  render() {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

我一直在定义我的减速器的“CHOOSE_YEAR”情况。我将如何定义这种情况,以便:

  1. 更新selectedYear
  2. 进行 api 调用https://website?property=${year},然后填充matchData
  3. 更新firstCall

这是我当前的重构。https://codesandbox.io/s/gracious-pare-um66h?file=/src/FootballMatches.js

Dre*_*ese 6

您似乎对减速器模式不熟悉。减速器是纯函数,采用状态对象和应用于该状态的操作,并返回下一个状态对象。减速器函数的副作用为零。

当状态更新时使用useEffect钩子来获取数据。year您可能不想同时对年份列表选项使用锚标记,因为单击该标记可能会尝试导航或重新加载应用程序/页面。

const initialState = {
  selectedYear: null,
  competitions: [],
  firstCall: false
};

const footballReducer = (state, action) => {
  switch (action.type) {
    case "CHOOSE_YEAR":
      return {
        selectedYear: action.year, // <-- save year payload
        firstCall: true
      };

    case "FETCH_BY_YEAR_SUCCESS":
      return {
        ...state, // <-- copy existing state
        competitions: action.competitions // <-- save competitions payload
      };
    default:
      throw new Error();
  }
};

const FootballMatches = () => {
  const [state, dispatchFootball] = useReducer(footballReducer, initialState);

  const yearChooseHandler = (year) => {
    dispatchFootball({ type: "CHOOSE_YEAR", year });
  };

  useEffect(() => {
    if (state.year) { // <-- ensure year value is truthy since null on initial render
      axios.get(`https://website?property=${state.year}`).then((res) => { // <-- access state.year for URL
        dispatchFootball({
          type: "FETCH_BY_YEAR_SUCCESS",
          competitions: res.data,
          firstCall: true
        });
      }
    });
  }, [state.year]); // <-- year dependency

  let years = [2011, 2012, 2013, 2014, 2015, 2016, 2017];
  return (
    <div>
      <div>Select Year</div>
      <ul>
        {years.map((year, idx) => {
          return (
            <li
              onClick={() => yearChooseHandler(year)} // <-- fix callback so it isn't invoked immediately and cause infinite render looping
              key={idx}
            >
              {year}
            </li>
          );
        })}
      </ul>

      ...
    </div>
  );
};
Run Code Online (Sandbox Code Playgroud)