Я новичок в редуксе, и мне трудно найти хорошее руководство, которое использует вызовы asyn c и машинопись. Я пытался понять это сам, но я немного застрял. Если бы кто-то мог взглянуть на мой код и, возможно, дать мне обратную связь и / или предложения относительно того, как я могу решить эту проблему, я был бы очень признателен!
// types.ts file
export const FETCH_USERS_REQUEST = 'FETCH_USERS_REQUEST';
export const FETCH_USERS_SUCCESS = 'FETCH_USERS_SUCCESS';
export const FETCH_USERS_FAILURE = 'FETCH_USERS_FAILURE';
^ Здесь я определяю константы для согласованности.
// userActions.ts
import { FETCH_USERS_FAILURE, FETCH_USERS_REQUEST, FETCH_USERS_SUCCESS } from './types';
import { Dispatch } from 'redux';
import axios, { AxiosResponse } from 'axios';
export interface UserProps {
id: number
name: string
email: string
}
export const fetchUsersRequest = () => {
return {
type: FETCH_USERS_REQUEST,
};
};
export const fetchUsersSuccess = (users: Array<UserProps>) => {
return {
type: FETCH_USERS_SUCCESS,
users: users,
};
};
export const fetchUsersFailure = (error: string) => {
return {
type: FETCH_USERS_FAILURE,
error: error,
};
};
export const fetchUsers = () => {
return (dispatch: Dispatch): Promise<unknown> => {
dispatch(fetchUsersRequest());
return axios.get('https://jsonplaceholder.typicode.com/users')
.then((response: AxiosResponse<UserProps[]>) => {
dispatch(fetchUsersSuccess(response.data));
return response.data;
})
.catch((error: string) => {
dispatch(fetchUsersFailure(error));
});
};
};
userReducer
import { UserProps } from '../actions/userActions';
import { FETCH_USERS_FAILURE, FETCH_USERS_REQUEST, FETCH_USERS_SUCCESS } from '../actions/types';
interface Action {
type: string
payload: Array<UserProps> | string,
}
export interface initialStateProps {
loading: boolean,
users: Array<UserProps>
error: string
}
const initialState: initialStateProps = {
loading: false,
users: [],
error: '',
};
export const userReducer = (state = initialState, action: Action) => {
switch (action.type) {
case FETCH_USERS_REQUEST:
return {
...state,
loading: true,
};
case FETCH_USERS_SUCCESS:
return {
loading: false,
users: action.payload,
};
case FETCH_USERS_FAILURE:
return {
loading: false,
users: [],
error: action.payload,
};
default: {
return state;
}
}
};
export const getUsers = (state: initialStateProps) => state.users;
export const getUsersRequest = (state: initialStateProps) => state.loading;
export const getUsersFailure = (state: initialStateProps) => state.error;
А затем для своего проекта я использую connected-router
, чтобы помочь отслеживать маршруты.
import { combineReducers } from 'redux';
import { History } from 'history';
import { connectRouter } from 'connected-react-router';
import { userReducer } from './userReducers';
export const createRootReducer = (history: History) => combineReducers({
router: connectRouter(history),
userReducer,
});
Магазин:
import { createBrowserHistory } from 'history';
import { applyMiddleware, compose, createStore } from 'redux';
import thunkMiddleware from 'redux-thunk'
import { createLogger } from 'redux-logger';
import { routerMiddleware } from 'connected-react-router';
import { createRootReducer } from './reducers';
export const history = createBrowserHistory();
const loggerMiddleware = createLogger();
export const configureStore = (preloadedState?: any) => {
const composeEnhancer: typeof compose = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
return createStore(
createRootReducer(history),
preloadedState,
composeEnhancer(
applyMiddleware(
routerMiddleware(history),
thunkMiddleware,
loggerMiddleware,
),
),
);
};
И в приложении я использую это:
const mapStateToProps = (state: initialStateProps) => ({
error: getUsersFailure(state),
users: getUsers(state),
loading: getUsersRequest(state)
});
const mapDispatchToProps = (dispatch: Dispatch) => bindActionCreators({
fetchUsers: fetchUsers
}, dispatch);
export default connect(
mapStateToProps,
mapDispatchToProps,
)(TopbarNav);
Но когда я console.log(props);
, я получаю:
users: undefined
loading: undefined
error: undefined
EDIT: Здесь я запускаю fetchUsers:
const TopbarNav: React.FC = (props: any) => {
const [loading, setLoading] = React.useState(true);
const classes = useStyles();
useEffect(() => {
props.fetchUsers();
});
const handler = () => {
console.log({props});
};
};
Я оставил метод рендеринга в этом вопросе.
EDIT 2 обновлен метод useEffect:
const [users, setUsers] = React.useState([]);
const [loading, setLoading] = React.useState(true);
const classes = useStyles();
useEffect(() => {
setUsers(props.fetchUsers());
}, [users, props, loading]);
const handler = () => {
console.log(props.loading);
};