[英]React-Redux + Redux-Thunk on functional component. Update UI after data is fetched from API
[英]React Functional Component, Redux and Loading Data
我目前正在尝试获取功能性反应,并且很难找出在页面加载时从 API 加载数据的适当方法。 我正在使用反应,redux 和 thunk。 我已经修改了我从本课程创建的项目。 我的代码目前看起来像这样
store.js
import {createStore, applyMiddleware, compose} from "redux";
import rootReducer from "./reducers";
import reduxImmutableStateInvariant from 'redux-immutable-state-invariant';
import thunk from "redux-thunk";
export default function configureStoreDev(initialState){
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // add support for redux dev tools
return createStore(
rootReducer,
initialState,
composeEnhancers(applyMiddleware(thunk, reduxImmutableStateInvariant()))
);
}
作者Api.js
import { handleResponse, handleError } from "./apiUtils";
const baseUrl = process.env.API_URL + "/authors/";
export function getAuthors() {
return fetch(baseUrl)
.then(handleResponse)
.catch(handleError);
}
作者Actions.js
import * as actionTypes from "./actionTypes";
import * as authorApi from "../../api/authorApi";
import {apiCallError, beginApiCall} from "./apiStatusAction";
export function loadAuthorsSuccess(authors){
return {type: actionTypes.LOAD_AUTHORS_SUCCESS, authors: authors};
}
export function loadAuthors(){
return function(dispatch){
// invoke loader
dispatch(beginApiCall());
return authorApi.getAuthors().then(response => {
dispatch(loadAuthorsSuccess(response.authors));
}).catch(error => {
dispatch(apiCallError());
throw error;
})
}
}
作者Reducer.js
import * as actionTypes from "../actions/actionTypes";
import initialState from "./initialState";
export default function authorReducer(state = initialState.authors, action){
switch(action.type){
case actionTypes.LOAD_AUTHORS_SUCCESS:
return action.authors;
default:
return state;
}
}
AuthorsPage.js
import React, {useState, useEffect} from 'react';
import {connect} from 'react-redux';
import AuthorsList from "./AuthorsList";
import Spinner from "../common/Spinner";
import {loadAuthors} from "../../redux/actions/authorActions";
import {loadCourses} from "../../redux/actions/courseActions";
function AuthorsPage({loadAuthors, deleteAuthor, loadCourses, ...props}) {
const [authors, setAuthors] = useState([...props.authors]);
const [courses, setCourses] = useState([...props.courses]);
const [loading, setLoading] = useState(props.loading);
const [redirectToAddAuthorPage, setRedirectToAddAuthorPage] = useState(false);
useEffect(() => {
loadAuthors().catch(error => {
console.log("Loading authors failed: " + error);
});
loadCourses().catch(error => {
console.log("Loading courses failed: " + error);
});
}, []);
useEffect(() => {
if(authors !== props.authors && props.authors.length > 0){
setAuthors([...props.authors]);
}
}, [props.authors]);
useEffect(() => {
setLoading(props.loading)
}, [props.loading]);
return (
<>
<h2>Authors</h2>
{loading === true ? <Spinner/> : (
<>
<button
style={{ marginBottom: 20 }}
className="btn btn-primary add-course"
onClick={() => setRedirectToAddAuthorPage(true )}
>
Add Author
</button>
<AuthorsList authors={authors} />
</>
)}
</>
);
}
function mapStateToProps(state){
return {
authors: state.authors,
courses: state.courses,
loading: state.apiCallsInProgress > 0
}
}
const mapDispatchToProps = {
loadAuthors: loadAuthors,
loadCourses: loadCourses
}
export default connect(mapStateToProps, mapDispatchToProps)(AuthorsPage);
我遇到问题的部分是让作者列表正确设置 state。 我尝试在调用loadAuthors()
之后设置它,但没有在该调用的 .then( .then()
中返回作者列表。
下一个选项是使用useEffect
监听作者的 props 变化,但这似乎不是加载我在初始加载时需要的数据的最有效或正确的方法。
我似乎无法找到任何文章或教程,详细说明从功能组件的角度完成此任务的适当方法,并且希望在正确方向上提供任何指导或指示。
下一个选项是使用 useEffect 监听作者的 props 变化,但这似乎不是加载我在初始加载时需要的数据的最有效或正确的方法。
您可以直接渲染props.authors
而无需将其分配给useState
例子
const thunk = ReduxThunk.default; const { connect, Provider } = ReactRedux; const { bindActionCreators, combineReducers, createStore, applyMiddleware } = Redux; window.redux = Redux; const initialState = { authors: [] }; const getAuthors = () => Promise.resolve(Array(10).fill(0).map((pr, index) => ({id: index, name: `Author ${index + 1}`}))) const loadAuthorsSuccess = (authors) => { return {type: 'LOAD_AUTHORS_SUCCESS', authors}; } const loadAuthors = () => { return function(dispatch) { return getAuthors().then(authors => { dispatch(loadAuthorsSuccess(authors)); }) } } const authorReducer = (state = initialState.authors, action) => { switch(action.type) { case 'LOAD_AUTHORS_SUCCESS': return action.authors; default: return state; } } const reducer = combineReducers({ authors: authorReducer}) const store = createStore( reducer, initialState, applyMiddleware(thunk) ); const { useState, useEffect } = React; function mapStateToProps({authors}) { return { authors } } const mapDispatchToProps = { loadAuthors } const _AuthorsPage = ({loadAuthors, authors}) => { useEffect(() => { loadAuthors().catch(error => { console.log("Loading authors failed: " + error); }); }, []) return <div> {authors.map(({id, name}) => <div key={id}>{name}</div>)} </div> } const AuthorsPage = connect(mapStateToProps, mapDispatchToProps)(_AuthorsPage) const App = () => { return <div> <AuthorsPage/> </div> } ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
<script src="https://unpkg.com/react/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> <script src="https://unpkg.com/redux@4.0.5/dist/redux.js"></script> <script src="https://unpkg.com/react-redux@latest/dist/react-redux.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/redux-thunk/2.3.0/redux-thunk.js"></script> <div id="root"></div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.