私は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
});
}
は;)あなたの助けをありがとうございました。 – zappee
喜んで:) – Alexander