如何在useReducer中调用api?
How to make api call in useReducer?
这是一个 class 组件,我想使用 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() {
...
}
}
我一直在定义我的减速器的 'CHOOSE_YEAR' 案例。
我将如何定义这种情况,以便它:
- 更新
selectedYear
- 对
https://website?property=${year}
进行 api 调用,然后填充 matchData
- 更新
firstCall
这是我目前的重构。 https://codesandbox.io/s/gracious-pare-um66h?file=/src/FootballMatches.js
您似乎对reducer 模式不熟悉。 Reducers 是采用状态对象和应用于该状态的操作的纯函数,以及 returns 下一个状态对象。 reducer函数中有zeroside-effects
当状态 year
更新时,使用 useEffect
挂钩获取数据。您可能不希望也为年份列表选项使用锚标记,因为单击它可能会尝试导航或重新加载 app/page。
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>
);
};
这是一个 class 组件,我想使用 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() {
...
}
}
我一直在定义我的减速器的 'CHOOSE_YEAR' 案例。 我将如何定义这种情况,以便它:
- 更新
selectedYear
- 对
https://website?property=${year}
进行 api 调用,然后填充matchData
- 更新
firstCall
这是我目前的重构。 https://codesandbox.io/s/gracious-pare-um66h?file=/src/FootballMatches.js
您似乎对reducer 模式不熟悉。 Reducers 是采用状态对象和应用于该状态的操作的纯函数,以及 returns 下一个状态对象。 reducer函数中有zeroside-effects
当状态 year
更新时,使用 useEffect
挂钩获取数据。您可能不希望也为年份列表选项使用锚标记,因为单击它可能会尝试导航或重新加载 app/page。
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>
);
};