如何在 Redux api 调用期间在组件上设置加载布尔值
How to set a loading boolean on component during Redux api call
我正在创建一个基于 React, Redux and Redux-Thunk 的项目。
在下面的示例中,我列出了每个 "project" 并允许用户 "Increment"(对 API 进行了 1 秒的虚假调用)并更新了 MainApp 组件的状态(以显示加载中)
问题:
如何在 incrementProject
操作完成后直接进入 MainApp 组件?
我搜索了很多关于它的内容,但没有找到任何东西。处理这种情况最好的方法是什么?
想法:
将所有状态创建到 Redux 项目存储中并全局处理所有加载状态? (我担心代码会更重:/)
将回调发送到 incrementProject(projectId, next)
并在调度错误或成功后从操作中调用它?
我没有包含所有 actions/reducers/api 调用,因为它是非常基本的代码。
MainApp 组件
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect, Provider } from 'react-redux';
import { requestProjects, incrementProject } from '../actions';
class MainApp extends Component {
constructor(props) {
super(props);
this.state = { loadingProjectsIds: [] };
}
componentDidMount() {
const { requestProjects } = this.props;
requestProjects();
}
render() {
const { projectStore, incrementProject } = this.props;
const { loadingProjectsIds } = this.state;
const incrementProject = (project) => {
let ids = this.state.loadingProjectsIds;
ids.push(project._id);
this.setState({
loadingProjectsIds: ids
});
incrementProject(project._id);
}
return (
<ul>
{projectStore.projects.map(project => (
<li key={`project-${project.key}`}>
{project.name}
{
loadingProjectsIds.indexOf(project._id) !== -1)
? Incrementing...
: <a>Increment</a>
}
</li>
))}
</ul>
);
}
};
export default connect((state) => { project } = state), (dispatch) => ({
requestProjects: () => dispatch(requestProjects()),
incrementProject: (_id) => dispatch(incrementProject(_id)),
})(MainApp);
增量动作
export function incrementProject(projectId) {
return async dispatch => {
dispatch({type: 'PROJECT_INC', projectId});
let { err, payload } = await API.incProject({projectId});
if (err) {
dispatch({type: 'PROJECT_INC_ERR', err});
}
else {
dispatch({type: 'PROJECT_INC_SUCCESS', payload});
}
};
};
没有最佳解决方案。如果给定的 action
被调度,一切都取决于谁感兴趣。一个更通用的方法(我们使用的)是在你的减速器中有一个 TOGGLE_LOADING
动作和一个 loading
属性。像这样
const initialState = {
value : '',
loading: false,
error: false
}
export const reducer = (state = initialState, action) =>{
switch(action.type){
case 'TOGGLE_LOADING' : return{
...state,
loading : !state.loading
}
case 'STORE_VALUE' : return{
...state,
loading: false
}
case 'ERROR_FETCHING' : return{
...state,
loading : false,
error: true,
}
default : return state
}
}
在你的action creator
里面
const fetchValue = () =>{
return dispatch =>{
dispatch({type: 'TOGGLE_LOAD'})
apiCall()
.then(value =>{
dispatch({type: 'STORE_VALUE'})
})
.catch(error =>{
dispatch({type: 'FETCH_ERROR'})
})
}
}
现在您的 state
中配置了 loading
属性。只需在您的组件中使用它
class Component extends React.Component{
componentDidMount(){
fetchValue()
}
render(){
const { loading } = this.props
return loading ? 'Loading' : <Content />
}
}
我正在创建一个基于 React, Redux and Redux-Thunk 的项目。
在下面的示例中,我列出了每个 "project" 并允许用户 "Increment"(对 API 进行了 1 秒的虚假调用)并更新了 MainApp 组件的状态(以显示加载中)
问题:
如何在 incrementProject
操作完成后直接进入 MainApp 组件?
我搜索了很多关于它的内容,但没有找到任何东西。处理这种情况最好的方法是什么?
想法:
将所有状态创建到 Redux 项目存储中并全局处理所有加载状态? (我担心代码会更重:/)
将回调发送到
incrementProject(projectId, next)
并在调度错误或成功后从操作中调用它?
我没有包含所有 actions/reducers/api 调用,因为它是非常基本的代码。
MainApp 组件
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect, Provider } from 'react-redux';
import { requestProjects, incrementProject } from '../actions';
class MainApp extends Component {
constructor(props) {
super(props);
this.state = { loadingProjectsIds: [] };
}
componentDidMount() {
const { requestProjects } = this.props;
requestProjects();
}
render() {
const { projectStore, incrementProject } = this.props;
const { loadingProjectsIds } = this.state;
const incrementProject = (project) => {
let ids = this.state.loadingProjectsIds;
ids.push(project._id);
this.setState({
loadingProjectsIds: ids
});
incrementProject(project._id);
}
return (
<ul>
{projectStore.projects.map(project => (
<li key={`project-${project.key}`}>
{project.name}
{
loadingProjectsIds.indexOf(project._id) !== -1)
? Incrementing...
: <a>Increment</a>
}
</li>
))}
</ul>
);
}
};
export default connect((state) => { project } = state), (dispatch) => ({
requestProjects: () => dispatch(requestProjects()),
incrementProject: (_id) => dispatch(incrementProject(_id)),
})(MainApp);
增量动作
export function incrementProject(projectId) {
return async dispatch => {
dispatch({type: 'PROJECT_INC', projectId});
let { err, payload } = await API.incProject({projectId});
if (err) {
dispatch({type: 'PROJECT_INC_ERR', err});
}
else {
dispatch({type: 'PROJECT_INC_SUCCESS', payload});
}
};
};
没有最佳解决方案。如果给定的 action
被调度,一切都取决于谁感兴趣。一个更通用的方法(我们使用的)是在你的减速器中有一个 TOGGLE_LOADING
动作和一个 loading
属性。像这样
const initialState = {
value : '',
loading: false,
error: false
}
export const reducer = (state = initialState, action) =>{
switch(action.type){
case 'TOGGLE_LOADING' : return{
...state,
loading : !state.loading
}
case 'STORE_VALUE' : return{
...state,
loading: false
}
case 'ERROR_FETCHING' : return{
...state,
loading : false,
error: true,
}
default : return state
}
}
在你的action creator
const fetchValue = () =>{
return dispatch =>{
dispatch({type: 'TOGGLE_LOAD'})
apiCall()
.then(value =>{
dispatch({type: 'STORE_VALUE'})
})
.catch(error =>{
dispatch({type: 'FETCH_ERROR'})
})
}
}
现在您的 state
中配置了 loading
属性。只需在您的组件中使用它
class Component extends React.Component{
componentDidMount(){
fetchValue()
}
render(){
const { loading } = this.props
return loading ? 'Loading' : <Content />
}
}