使用从外部API

时间:2018-02-08 19:15:11

标签: reactjs rest redux react-redux

让我们说react使用redux redux-thunk中间件

进行简单的纸牌游戏

我从外部API获取了一副牌,所以我的动作创建者看起来像这样:

const fetchDeck = {    
    return dispatch => {
        return fetch(https://some.api.with.cards/)
        .then(r => r.json())
        .then(data => dispatch({type:"FETCH_DECK", deck: data}))
    }
}

相应的减速器是:

const deck = (state=[], action) => {
    switch(action.type) {
        case "FETCH_DECK":
            return action.deck

        default:
            return state
    }
}

来自API的响应是一组卡对象,如下所示:

{
    name: "ACE",
    suit: "CLUBS"
}

所以现在我想向商店添加hand道具。 hand是一个数组,其中包含已经在玩家手中的牌,所以我创建了一个动作,允许从deckhand的牌:

const drawCard = (deck, numberOfCards) => {
    return {
        type: "DRAW_CARD",
        deck
    }
}

这是相应的减速器:

const hand = (state=[], action) {
    switch(action.type) {
        case "DRAW_CARD":
            return [...state.slice(0,action.deck)
        default:
            return state
    }
}

最后,我尝试在<Hand>组件中实现此行为:

class Hand extends React.component {
    componentDidMount() {
        const { deck, drawCards } = this.props;
        drawCards(deck, 5)
    }
}

但它不起作用! componentDidMount()发生时,API请求未完成。我想到的唯一能解决问题的是:

componentDidUpdate(prevProps) {
    if (prevProps.deck.length > 0) {
        const { deck, drawCard } = this.props;
        drawCard(deck, 5)
    }
}

这是有效的,但我有一种尴尬的感觉,这不是正确的方法。此外,如果以这种方式应用,有必要使用更多的条件来防止意外行为。

有没有更好的方法来处理我的问题?

2 个答案:

答案 0 :(得分:2)

我认为问题在于方法。而不是在一个地方初始化套牌并交给另一个地方(componentDidMount) - 您可以创建init动作,该动作在根组件componentDidMount上调用。

可能看起来像这样:

function init() {
  return (dispatch, getState) => {
     dispatch(fetchDeck()).then(() => dispatch(drawCard(getState().deck, 5)))
  }
}

答案 1 :(得分:0)

首先,您必须在使用之前验证甲板是否已被取出,Array.isArray(deck) && drawCard()之类的东西会更安全。其次,检测到新道具到达的正确位置是componentWillReciveProps(),如果获取了甲板,则可以安全地调用drawCard()