现在,我有一个使用redux的react应用程序。我已经创建了一个用作创建客户的表单的组件。如下所示:
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状态。就像这样:
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 (通过某些错误或完全可以)。
发布于 2020-01-12 20:19:17
使用componentDidUpdate生命周期函数。在redux中添加表单处理成功操作和状态,并将其映射到道具。
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
);或者作为一个功能组件,使用状态和效果挂钩:
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
);发布于 2020-01-25 00:53:21
我使用这篇博客文章进行了一些更改,将加载状态与实际操作分开:
我创建了这样一个loadingReducer:
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:
import _ from 'lodash';
export const createLoadingSelector = (actions) => (state) => {
// returns true only when all actions is not loading
return _(actions)
.some((action) => _.get(state, action));
};然后创建一个基于该减速器更改状态的组件:
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)
};
};https://stackoverflow.com/questions/59707587
复制相似问题