我试图显示加载,直到RootContainer中的所有组件都完成了它们的api调用,但我的应用程序在调用调度操作的内循环中运行,应用程序始终处于加载状态。它在30秒内打了大约1300个电话。这是我的密码。我不知道为什么应用程序运行在infinte循环中。
App.js
import React, { Component } from 'react';
import RootContainer from './components/RootContainer'
import {Provider} from 'react-redux'
import store from './redux/store';
class App extends Component {
render() {
return (
<Provider store={store}>
<div className="App">
<RootContainer/>
</div>
</Provider>
)
}
}
export default App;
RootContainer.js
import React from 'react'
import {connect} from 'react-redux'
import {mapStateToProps , mapDispatchToprops} from './mapFunctions.js'
import UserContainer from './UserContainer'
import TodoContainer from './TodoContainer'
class RootContainer extends React.Component{
render(){
if(this.props.userData.count===0){
return (
<div>
<UserContainer/>
<TodoContainer/>
</div>
);
}else{
return(
<h2> Loading... </h2>
)
}
}
}
export default connect(mapStateToProps,mapDispatchToprops)(RootContainer)
UserContainer.js
import React from 'react'
import {connect} from 'react-redux'
import {mapStateToProps , mapDispatchToprops} from './mapFunctions.js'
class UserContainer extends React.Component{
constructor(props){
super(props)
this.state={
userList:[]
}
}
componentDidMount() {
this.props.fetchUsers('https://jsonplaceholder.typicode.com/users').then(data =>{
this.setState({
userList:data
})
})
}
render(){
console.log("count = "+this.props.userData.count);
return (
<div>
<h2>User List</h2>
<ul>
{this.state.userList.map(item => {
return <li>{item.name}</li>;
})}
</ul>
</div>
)
}
}
export default connect(mapStateToProps,mapDispatchToprops)(UserContainer)
TodoContainer.js
import {connect} from 'react-redux'
import { fetchUsers } from '../redux'
import {mapStateToProps , mapDispatchToprops} from './mapFunctions.js'
class TodoContainer extends React.Component{
constructor(props){
super(props)
this.state={
todoList:[]
}
}
componentDidMount() {
this.props.fetchUsers('https://jsonplaceholder.typicode.com/todos').then(data =>{
this.setState({
todoList:data
})
})
}
render(){
return (
<div>
<h2>ToDo List</h2>
<ul>
{this.state.todoList.map(item => {
return <li>{item.title}</li>;
})}
</ul>
</div>
)
}
}
export default connect(mapStateToProps,mapDispatchToprops)(TodoContainer)
UserActions.js
import { INCREMENT_COUNT ,DECREMENT_COUNT} from "./userTypes"
import axios from 'axios'
export const incrementCount = () =>{
return {
type:INCREMENT_COUNT
}
}
export const decrementCount = () =>{
return {
type:DECREMENT_COUNT
}
}
export const fetchUsers = (url) =>{
console.log("fetchUsers called" + url)
return(dispatch) => {
dispatch(incrementCount())
return fetch(url)
.then(response => {
dispatch(decrementCount());
return response.data
})
.catch(error => {
const errorMsg = error.message
console.log("error = "+errorMsg)
dispatch(decrementCount());
})
}
}
UserReducer.js
import {INCREMENT_COUNT ,DECREMENT_COUNT} from "./userTypes"
const initialState = {
count:0,
}
const reducer = (state = initialState,action) => {
switch(action.type){
case INCREMENT_COUNT:
console.log("reducer called =increment")
return{
count: state.count+1,
}
case DECREMENT_COUNT:
return{
count:Math.max(0,state.count-1),
}
default: return state
}
}
export default reducer
mapFunctions.js
import { fetchUsers } from '../redux'
export const mapStateToProps = state =>{
return {
userData: state.user
}
}
export const mapDispatchToprops = dispatch =>{
return {
fetchUsers: (url) => dispatch(fetchUsers(url))
}
}
rootReducer.js
import { combineReducers } from 'redux'
import userReducer from './user/userReducer'
const rootReducer = combineReducers ({
user:userReducer
})
export default rootReducer
store.js
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'
import logger from 'redux-logger'
import rootReducer from './rootReducer'
const store = createStore(rootReducer,
composeWithDevTools(applyMiddleware(thunk,logger))
)
export default store
但我的应用程序运行在调度操作的infint循环中被调用,并且应用程序始终处于加载状态。它在30秒内打了大约1300个电话。这是我的密码。我不能以查找应用程序在infinte循环中运行的原因。
更新:使用新操作将redux
功能重构为单独的组件,以检查是否有任何API调用正在进行中。这是一个完美的沙盒。
//UserActions.js
import * as types from "./actionType";
import { beginApiCall, apiCallError } from "./apiStatusAction";
import { handleResponse, handleError } from "./apiUtils";
export function fetchUsersSuccess(users) {
return { type: types.LOAD_USERS_SUCCESS, users };
}
export function fetchUsers(url) {
return (dispatch) => {
dispatch(beginApiCall());
return getUsers(url)
.then((users) => {
dispatch(fetchUsersSuccess(users));
})
.catch((error) => {
dispatch(apiCallError(error));
throw error;
});
};
}
export function getUsers(url) {
return fetch(url).then(handleResponse).catch(handleError);
}
//apiStatusAction.js
import * as types from "./actionType";
export function beginApiCall() {
return { type: types.BEGIN_API_CALL };
}
export function apiCallError() {
return { type: types.API_CALL_ERROR };
}
此减少程序检查是否有任何子字符串_SUCCESS
仍在进行中的操作。如果是,则initialState
按其递减值的另一个值递增。
import * as types from "../actions/actionType";
import initialState from "./initialState";
function actionTypeEndsInSuccess(type) {
return type.substring(type.length - 8) === "_SUCCESS";
}
export default function apiCallStatusReducer(
state = initialState.apiCallsInProgress,
action
) {
if (action.type == types.BEGIN_API_CALL) {
return state + 1;
} else if (
action.type === types.API_CALL_ERROR ||
actionTypeEndsInSuccess(action.type)
) {
return state - 1;
}
return state;
}
这就是如何利用apiStatus
reducer来渲染组件中的微调器。
//UserContainer.js
import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchUsers } from "../redux/actions/UserActions";
import Spinner from "./Spinner";
function UserContainer() {
const userList = useSelector((state) => state.user);
const loading = useSelector((state) => state.apiCallsInProgress > 0);
const dispatch = useDispatch();
const fetchUserList = () => {
dispatch(fetchUsers("https://jsonplaceholder.typicode.com/users")).catch(
(error) => {
alert("Loading users failed" + error);
}
);
};
useEffect(() => {
fetchUserList();
}, []);
if (loading) {
return <Spinner />;
}
return (
<div>
<h1>Users</h1>
{userList.map((user) => {
return <li key={user.id}>{user.name}</li>;
})}
</div>
);
}
export default UserContainer;