2016-12-05 11 views
1

私はreact + reduxで問題があります。私は最初のreduxベースのアプリケーションを稼働させようとしていますが、無限ループが発生します。react + redux無限ループを作成

私のデモアプリケーションにはボタンが1つしか含まれていません。そのボタンをクリックすると、残りのAPI呼び出しを実行したいと思います。しかし、私はWebブラウザで私のアプリのURLを開いたとき、私は、残りのAPIは無限ループで自動的に呼び出され、私はなぜそうではないコンソールログに見ることができます。手伝っていただけませんか?

これは、コンソールログです:

--- start -------------------- 
dispatching Object { type="waiting-for-response", waitingForResponse=true, hasError=false} 
next state Object { waitingForResponse=true, hasError=false} 
----- end -------------------- 
posting... 
waiting-for-response 
--- start -------------------- 
dispatching Object { type="waiting-for-response", waitingForResponse=true, hasError=false} 
next state Object { waitingForResponse=true, hasError=false} 
----- end -------------------- 
... 
show-cards 
> --- start -------------------- 
dispatching Object { type="show-cards", waitingForResponse=false, hasError=false} 
Warning: setState(...): Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`. 
next state Object { waitingForResponse=false, hasError=false} 
----- end ---------------------- 

要求応答ログ:

GET /demo/ > 200 OK 
GET bootstrap.min.css > 200 OK 
GET bootstrap-theme.min.css > 200 OK 
GET bundle.js > 200 OK 
GET time.jsontest.com > 200 OK 
GET time.jsontest.com > 200 OK 
GET time.jsontest.com > 200 OK 
... 

ソース:

App.js

const logger = store => next => action => { 
    console.group(action.type); 
    console.log('--- start --------------------'); 
    console.log('dispatching', action); 
    let result = next(action); 
    console.log('next state', store.getState()); 
    console.log('--- end ----------------------'); 
    console.groupEnd(action.type); 
    return result 
}; 

let store = createStore(reducers, applyMiddleware(thunk, logger)); 

ReactDom.render(
    <Provider store={store}> 
     <Card/> 
    </Provider>, 
    document.getElementById('root') 
); 

Card.js

class Card extends React.Component { 
    render() { 
     return (
      <div> 
       {this.props.waitingForResponse ? <p>fetching...</p> : null} 
       {this.props.hasError ? <p>service is not available, try it later</p> : null} 
       <Button onClick={this.props.getCards('param1', 'param2')}>Button</Button> 
      </div> 
     ) 
    } 
} 

const mapStateToProps = (state) => { 
    return { 
     waitingForResponse: state.waitingForResponse, 
     hasError: state.hasError 
    }; 
}; 

const mapDispatchToProps = (dispatch) => { 
    return { 
     getCards: (param1, param2) => dispatch(performPost(param1, param2)) 
    }; 
}; 

export default connect(mapStateToProps, mapDispatchToProps)(Card) 

CardActionType.js

export default { 
    WAITING_FOR_RESPONSE: 'waiting-for-response', 
    COMMUNICATION_ERROR: 'communication-error', 
    SHOW_CARDS: 'show-cards' 
} 

CardAction.js

const waitingForResponse =() => { 
    return { 
     type: CardActionType.WAITING_FOR_RESPONSE, 
     waitingForResponse: true, 
     hasError: false 
    } 
}; 

const communicationError =() => { 
    return { 
     type: CardActionType.COMMUNICATION_ERROR, 
     waitingForResponse: false, 
     hasError: true 
    } 
}; 

const showCard =() => { 
    return { 
     type: CardActionType.SHOW_CARDS, 
     waitingForResponse: false, 
     hasError: false 
    } 
}; 

export function performPost(param1, param2) { 
    return (dispatch) => { 
     console.log("posting..."); 
     dispatch(waitingForResponse()); 

     axios({ 
      baseURL: 'http://time.jsontest.com/', 
      method: 'get' 
     }) 
      .then((response) => { 
       console.log('request performed successfully'); 
       dispatch(showCard()); 
      }) 
      .catch((response) => { 
       console.log('communication error'); 
       dispatch(communicationError()); 
      }); 
    } 
} 

Reducer.jsあなたが代わりにあなたがアクション・クリエーターを実行し、onClickのハンドラにコールバック関数を提供しないCardActionあなたのrenderメソッドで

const initialState = { 
    waitingForResponse: false, 
    hasError: false 
}; 

export default (state = initialState, action) => { 
    return Object.assign({}, state, { 
     waitingForResponse: action.waitingForResponse, 
     hasError: action.hasError 
    }); 
} 

答えて

0

。ある関数内でaction-creatorを呼び出す必要があります。そのため、それを太い矢印の関数として記述する必要があります。

何が起こるかは、すべてのレンダリングでaction-creatorが呼び出され、redux-storeを更新し続けるためレンダリング関数が呼び出され続けることです。

<Button onClick={() => this.props.getCards('param1', 'param2')}>Button</Button>

の代わり::だから、使用明確にする

class Card extends React.Component { 
    render() { 
     return (
      <div> 
       {this.props.waitingForResponse ? <p>fetching...</p> : null} 
       {this.props.hasError ? <p>service is not available, try it later</p> : null} 
       <Button onClick={() => this.props.getCards('param1', 'param2')}>Button</Button> 
      </div> 
     ) 
    } 
} 

とても速かった

<Button onClick={this.props.getCards('param1', 'param2')}>Button</Button>

+0

は;)あなたの助けをありがとうございました。 – zappee

+0

喜んで:) – Alexander

関連する問題