我正在尝试在用户注册时提交表单。单击提交按钮时,应执行操作创建者以启动异步操作,但实际上不会触发提交,也不会启动操作创建者。
actions.ts:
import { ActionTypes } from "./types";
import { SignUpUser, User } from "../apis/authentication";
import { AxiosError } from "axios";
import { Dispatch } from "redux";
export interface ReturnedUser {
username: string;
}
export interface SignUpSuccessAction {
type: ActionTypes.SucceedSignUp;
payload: ReturnedUser;
}
export interface SignUpFailAction {
type: ActionTypes.FailSignUp;
payload: string;
}
export interface SignUpStartAction {
type: ActionTypes.StartSignUp;
}
const signUpStarted = (): SignUpStartAction => ({
type: ActionTypes.StartSignUp
});
const signUpSucceeded = (user: ReturnedUser): SignUpSuccessAction => ({
type: ActionTypes.SucceedSignUp,
payload: user
});
const signUpFailed = (error: string): SignUpFailAction => ({
type: ActionTypes.FailSignUp,
payload: error
});
export const signUpFetch = (user: User) => {
return async (dispatch: Dispatch) => {
dispatch(signUpStarted());
SignUpUser(user).then(
(response: any) => {
const { username } = response;
return dispatch(signUpSucceeded(username));
},
(error: AxiosError) => {
let errorMessage = "Internal Server Error";
if (error.response) {
errorMessage = error.response.data;
}
return dispatch(signUpFailed(errorMessage));
}
);
};
};
减速器/减速器.ts:
import { Action, ActionTypes } from "../actions";
export const SignUpReducer = (state = {}, action: Action) => {
switch (action.type) {
case ActionTypes.SucceedSignUp:
return { ...state, user: action.payload };
case ActionTypes.FailSignUp:
return { ...state, error: action.payload };
default:
return state;
}
};
reducers/index.ts:
import { SignUpReducer } from "./signUp";
import { combineReducers } from "redux";
export const reducer = combineReducers({
signUp: SignUpReducer
});
index.tsx:
import React from "react";
import ReactDOM from "react-dom";
import SignUp from "./containers/Signup/SignUp";
import { Provider } from "react-redux";
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
import { reducer } from "./reducers/index";
const store = createStore(reducer, composeWithDevTools(applyMiddleware(thunk)));
const App = () => <SignUp />;
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
注册.tsx:
import React, { useState } from "react";
import Button from "@material-ui/core/Button";
import { connect } from "react-redux";
import { Form, Field } from "react-final-form";
import { makeStyles, Theme, createStyles } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import CardWrapper from "../../components/CardWrapper";
import PasswordField from "../../components/Password";
import TextField from "../../components/TextField";
import { validate, submit } from "./validation";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
container: {
padding: 16,
margin: "auto",
maxWidth: "100%",
flexGrow: 1
},
paper: {
padding: 16
},
item: {
marginTop: 16
}
})
);
const SignUp = () => {
const classes = useStyles();
const [showPassword, setPassword] = useState(false);
const handleClickShowPassword = () => {
setPassword(!showPassword);
};
const handleMouseDownPassword = (
event: React.MouseEvent<HTMLButtonElement>
) => {
event.preventDefault();
};
return (
<div className={classes.container}>
<Form
onSubmit={submit}
validate={validate}
render={({ handleSubmit, form, submitting, pristine }) => (
<form onSubmit={handleSubmit}>
<CardWrapper title='SignUp Form'>
<Grid container justify='center' spacing={3}>
<Grid item md={12}>
<Field fullWidth required name='username'>
{props => (
<TextField
label='Username'
type='text'
value={props.input.value}
onChange={props.input.onChange}
onBlur={props.input.onBlur}
meta={props.meta}
fullWidth={true}
/>
)}
</Field>
</Grid>
<Grid item md={12}>
<Field fullWidth required name='email'>
{props => (
<TextField
label='Email'
type='email'
value={props.input.value}
onChange={props.input.onChange}
onBlur={props.input.onBlur}
meta={props.meta}
fullWidth={true}
/>
)}
</Field>
</Grid>
<Grid item md={12}>
<Field fullWidth required name='password'>
{props => (
<PasswordField
value={props.input.value}
handleChange={props.input.onChange}
showPassword={showPassword}
handleClickShowPassword={handleClickShowPassword}
handleMouseDownPassword={handleMouseDownPassword}
fullWidth={true}
onBlur={props.input.onBlur}
meta={props.meta}
/>
)}
</Field>
</Grid>
<Grid item className={classes.item}>
<Button
type='button'
variant='contained'
onClick={form.reset}
disabled={submitting || pristine}
>
Reset
</Button>
</Grid>
<Grid item className={classes.item}>
<Button
variant='contained'
color='primary'
type='submit'
disabled={submitting || pristine}
>
Submit
</Button>
</Grid>
</Grid>
</CardWrapper>
</form>
)}
/>
</div>
);
};
export default connect()(SignUp);
验证.ts:
interface SignUpValues {
email: string;
password: string;
username: string;
}
const submit = (values: SignUpValues) => {
const user = {
username: values.username,
email: values.email,
password: values.password
};
return signUpFetch(user);
};
export { submit };
我发现一个类似的问题发布了一个类似的问题,关于Redux Dispatch在操作中创建器中不起作用的相同问题,但答案并不能解决我的问题。将不同的组件与 redux 链接时我是否出错了?
它不会调度,因为在组件中 你没有调度你的函数
return signUpFetch(user)
而是将组件与 Redux 连接并调度函数 in Index.tsx
import { connect } from 'react-redux';
const mapDispatchToProps = {
submit
};
export default connect(null, mapDispatchToProps)(SignUp);
并通过以下方式访问它
这.道具.提交
在提交功能中添加调度
const submit = (values: SignUpValues) =>(dispatch, getState)=> {
const user = {
username: values.username,
email: values.email,
password: values.password
};
return dispatch(signUpFetch(user));
};
每当需要更新 redux 状态时,请从调用它的位置以及在操作中调度函数。
执行调度时,您需要将组件连接到存储:
import { connect } from 'react-redux';
const submit = (values: SignUpValues) => {
const user = {
username: values.username,
email: values.email,
password: values.password
};
return this.props.signUpFetch(user);
};
export const connectedSubmit = connect(null, {signUpFetch})(submit);
import { validate, connectedSubmit as submit } from "./validation";
你也可以在SignUpUser
返回
export const signUpFetch = (user: User) => {
return async (dispatch: Dispatch) => {
dispatch(signUpStarted());
return SignUpUser(user).then(
(response: any) => {
const { username } = response;
dispatch(signUpSucceeded(username));
},
(error: AxiosError) => {
let errorMessage = "Internal Server Error";
if (error.response) {
errorMessage = error.response.data;
}
dispatch(signUpFailed(errorMessage));
}
);
};
}