首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Redux +Redux加载屏幕

使用Redux +Redux加载屏幕
EN

Stack Overflow用户
提问于 2020-01-12 19:54:01
回答 2查看 312关注 0票数 0

现在,我有一个使用redux的react应用程序。我已经创建了一个用作创建客户的表单的组件。如下所示:

代码语言:javascript
复制
import { createCustomer } from "../../actions";

class CustomerCreate extends React.Component {

  state = {
    submitting: false
  }

  componentWillReceiveProps(nextProps) {
    this.setState({ submitting: false });
  }

  submitData = (data) => {
    this.setState({ submitting: true });
    this.props.createCustomer(data);
  };

  render() {
    return (
      <React.Fragment>
        {this.state.submitting ? <LoadingScreen /> : null}
        {this.props.error ? <ErrorMessage message={this.props.error}/> : null}
        <FormContainer
        ...
        />
      </React.Fragment>
    );
  }
}

const mapStateToProps = ({ customerData }) => {
  return {
    error: customerData.error
  };
};

export default connect(mapStateToProps, { createCustomer })(
  CustomerCreate
);

这个“很好”。基本上,每次发生某些事情(错误,好的)时都会调用componentWillReceiveProps,所以我将知道何时删除LoadingScreen。问题是,componentWillReceiveProps正在抛出一个警告(说不应该使用),并且基于redux文档,这被标记为反模式。

我知道一种解决办法就是不要在这里使用redux。用轴子调用改变submitData,并将setState放在那里。但是我这样使用它,因为其中一条错误消息可能是:会话过期的无效的JWT令牌,所以我需要将网页重新发送到登录屏幕。

我认为另一种方法是在操作中调用一个调度来设置isSubmitting状态。就像这样:

代码语言:javascript
复制
export const createCustomer = (data) => {
  /* IS THIS VALID? */
  dispatch({ type: CUSTOMER_SUBMITTING });
  return async function (dispatch) {
    try {
      const response = await services.post("/api/customer", data, buildHeader());
      dispatch({ type: CUSTOMER_CREATED, payload: response.data });
    } catch (err) {
      dispatch({ type: CUSTOMER_ERROR, payload: err });
    }
  };
};

而不是使用state.isSubmitting,而是使用props.isSubmitting.但我不确定这样调用两个反路径是否有效/正确。

因此,我的问题是:如何实现在提交时设置为true的状态/道具,并在axios调用完成时设置为false (通过某些错误或完全可以)。

EN

回答 2

Stack Overflow用户

发布于 2020-01-12 20:19:17

使用componentDidUpdate生命周期函数。在redux中添加表单处理成功操作和状态,并将其映射到道具。

代码语言:javascript
复制
import { createCustomer } from "../../actions";

class CustomerCreate extends React.Component {

  state = {
    submitting: false
  }

  componentDidUpdate(prevState, prevProps) {
    // If a new error comes in and was previously "falsey" set submitting false
    if (prevProps.error !== this.props.error && this.props.error) {
      this.setState({ submitting: false });
    }
    // Similar check for form success
  }

  submitData = (data) => {
    this.setState({ submitting: true });
    this.props.createCustomer(data);
  };

  render() {
    return (
      <React.Fragment>
        {this.state.submitting ? <LoadingScreen /> : null}
        {this.props.error ? <ErrorMessage message={this.props.error}/> : null}
        <FormContainer
        ...
        />
      </React.Fragment>
    );
  }
}

const mapStateToProps = ({ customerData }) => {
  return {
    error: customerData.error,
    success: /* some success value from redux */
  };
};

export default connect(mapStateToProps, { createCustomer })(
  CustomerCreate
);

或者作为一个功能组件,使用状态和效果挂钩:

代码语言:javascript
复制
import { createCustomer } from "../../actions";

const CustomerCreate ({ createCustomer, error, success }) => {

  const [submitting, setSubmitting] = useState(false);

  useEffect(() => {
    if (error || success) setSubmitting(false);
  }, [error, success]);

  submitData = (data) => {
    setSubmitting(true);
    createCustomer(data);
  };

  return (
    <React.Fragment>
      {submitting ? <LoadingScreen /> : null}
      {error ? <ErrorMessage message={error}/> : null}
      <FormContainer
        ...
      />
    </React.Fragment>
  );
}

const mapStateToProps = ({ customerData }) => ({
  error: customerData.error,
  success: /* some success value from redux */
});

export default connect(mapStateToProps, { createCustomer })(
  CustomerCreate
);
票数 0
EN

Stack Overflow用户

发布于 2020-01-25 00:53:21

我使用这篇博客文章进行了一些更改,将加载状态与实际操作分开:

https://medium.com/stashaway-engineering/react-redux-tips-better-way-to-handle-loading-flags-in-your-reducers-afda42a804c6

我创建了这样一个loadingReducer:

代码语言:javascript
复制
const INITIAL_STATE = {
}

const loadingReducer = (state = INITIAL_STATE, action) => {
    const { type } = action;
    const matches = /(.*)_(DELETE|REQUEST|SUCCESS|FAILURE)/.exec(type);

    // not a *_REQUEST / *_SUCCESS /  *_FAILURE actions, so we ignore them
    if (!matches) return state;
    const [, requestName, requestState] = matches;
    return {
        ...state,
        // Store whether a request is happening at the moment or not
        // e.g. will be true when receiving GET_TODOS_REQUEST
        //      and false when receiving GET_TODOS_SUCCESS / GET_TODOS_FAILURE
        [requestName]: requestState === 'REQUEST',
        [requestName + '_DELETE']: requestState === 'DELETE',
    };
};

export default loadingReducer;

然后创建函数loadingSelector:

代码语言:javascript
复制
import _ from 'lodash';

export const createLoadingSelector = (actions) => (state) => {
    // returns true only when all actions is not loading
    return _(actions)
        .some((action) => _.get(state, action));
};

然后创建一个基于该减速器更改状态的组件:

代码语言:javascript
复制
class LoadingScreen extends React.Component {

    render() {
        if (!this.props.isLoading)
            return null;
        return (
            <Backdrop
                className={this.props.classes.backdrop}
                open={true}
            >
                <CircularProgress color="inherit" />
            </Backdrop>
        )
    }


}

const loadingListSelector = createLoadingSelector(['CUSTOMERS']);

const mapStateToProps = ({ loading }) => {
    return {
        isLoading: loadingListSelector(loading)
    };
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59707587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档