首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何让这个Formik逻辑像我想要的提交按钮那样工作

如何让这个Formik逻辑像我想要的提交按钮那样工作
EN

Stack Overflow用户
提问于 2020-12-21 01:47:26
回答 1查看 72关注 0票数 0

我学习了Reactjs,并使用了这个使用Formik的登录组件

我的问题是Facebook、Google和Twitter都能正常工作,但我不能使用密码登录。

当我单击Button时,将调用onSubmit={(values, { setSubmitting }) => {...values contain the email and password but I want the Button to use the same logic as Facebook, Google and Twitter按钮‘,如果可能的话。

你可以看到,当点击Facebook,Google和Twitter时,他们都会通过onClick={this.submitFormType...将状态设置为相应的提供者。然后它调用Formik handleSubmit

这也是我想要的提交Button,或者也许我应该重新考虑我的设计,而不是使用Formik。

代码语言:javascript
运行
复制
import React from 'react';
import { connect } from 'react-redux';
import { compose } from 'recompose';
import { Link as RouterLink } from 'react-router-dom';
import * as Yup from 'yup';
import { Formik } from 'formik';
import { Box, Button, Container, Grid, Link, TextField, Typography } from '@material-ui/core';
import { withStyles } from '@material-ui/core/styles';
import Dots from 'react-activity/lib/Dots';
import { withFirebase } from '../../../../firebase';
import FacebookIcon from '../../../../assets/Facebook';
import GoogleIcon from '../../../../assets/Google';
import TwitterIcon from '../../../../assets/twitter-logo';
import Page from '../../utils/Page';
import MotionDiv from '../../utils/MotionDiv';
import { withEmailVerification, withAuthorization, AuthUserContext } from '../../../../session';
import { changeToUserRole } from '../../../../redux/userData/user.actions';
import * as ROLES from '../../../../constants/roles';
import 'react-activity/lib/Dots/Dots.css';
import * as SIGN_IN from '../../../../constants/signinmethods';

const useStyles = theme => ({
    root: {
        backgroundColor: theme.palette.primary.light,
        minHeight: '100vh',
        paddingBottom: theme.spacing(3),
        paddingTop: theme.spacing(3),
    },
    container: {
        backgroundColor: theme.palette.primary.main,
        paddingTop: theme.spacing(3),
    },
    facebook: {
        backgroundColor: '#3b5999',
        color: 'white',
        '&:hover': {
            backgroundColor: '#4d70ba',
        },
    },
    google: {
        backgroundColor: '#ffffff',
        textColor: 'black',
    },
    twitter: {
        backgroundColor: '#ffffff',
        textColor: 'black',
    },
    button: {
        backgroundColor: theme.palette.primary.main,
        boxShadow: theme.shadows[5],
    },
});

const INITIAL_EMAIL_STATE = {
    email: '',
    password: '',
    error: null,
};

class LoginManagementBase extends React.Component {
    constructor() {
        super();
        this.state = {
            activeSignInMethods: [],
            anonymousSignIn: null,
            error: null,
            formType: null,
            ...INITIAL_EMAIL_STATE,
        };
        this.submitFormType = this.submitFormType.bind(this);
        this.facebookSignIn = this.facebookSignIn.bind(this);
        this.googleSignIn = this.googleSignIn.bind(this);
        this.twitteSignIn = this.twitteSignIn.bind(this);
    }

    componentDidMount() {
        this.fetchSignInMethods();
    }

    fetchSignInMethods = () => {
        const { firebase, authUser } = this.props;
        const email = authUser.email === null ? 'none@guest.ac' : authUser.email;
        firebase.auth
            .fetchSignInMethodsForEmail(email)
            .then(activeSignInMethods =>
                this.setState({
                    activeSignInMethods,
                    anonymousSignIn: activeSignInMethods.length === 0,
                    error: null,
                }),
            )
            .catch(error => this.setState({ error }));
    };

    onSocialLoginLink = provider => {
     // Do stuf to sign in..............
    };

    // this.setState({ count: this.state.count + 1 })

    submitFormType = (formTypeSubmited, handleSumitType) => () => {
        this.setState({
            formType: formTypeSubmited,
        });
        handleSumitType();
    };

    googleSignIn = () => {
        this.setState({
            formType: undefined,
        });
        this.onSocialLoginLink(SIGN_IN.WITH_GOOGLE.provider);
    };

    facebookSignIn = () => {
        this.setState({
            formType: undefined,
        });
        this.onSocialLoginLink(SIGN_IN.WITH_FACEBOOK.provider);
    };

    twitteSignIn = () => {
        this.setState({
            formType: undefined,
        });
        this.onSocialLoginLink(SIGN_IN.WITH_TWITTER.provider);
    };

    emailSignIn = values => {
        const { email, password } = values;
        const { firebase } = this.props;

        firebase.auth
            .signInWithEmailAndPassword(email, password)
            .then(() => {
                this.setState({ ...INITIAL_EMAIL_STATE });
                // this.props.history.push(ROUTES.HOME);
            })
            .catch(error => {
                this.setState({ error });
            });
    };

    render() {
        const { classes } = this.props;
        const { error } = this.state;
        const { saveRolesErr, isSavingRolesStarted } = this.props;
        if (error && error.message) {
            console.log(error.message);
        }
        return (
            <MotionDiv>
                <Page className={classes.root} title="Sign In">
                    <Box display="flex" flexDirection="column" height="100%" justifyContent="center">
                        <Container maxWidth="sm" className={classes.container}>
                            <Formik
                                initialValues={{
                                    email: 'demo@devias.io',
                                    password: 'Password123',
                                }}
                                validationSchema={Yup.object().shape({
                                    email: Yup.string().email('Must be a valid email').max(255).required('Email is required'),
                                    password: Yup.string().max(255).required('Password is required'),
                                })}
                                onSubmit={(values, { setSubmitting }) => {
                                    setSubmitting(false);
                                    const { formType } = this.state;
                                    if (formType) {
                                        if (formType === SIGN_IN.WITH_FACEBOOK.provider) {
                                            this.facebookSignIn();
                                        } else if (formType === SIGN_IN.WITH_GOOGLE.provider) {
                                            this.googleSignIn();
                                        } else if (formType === SIGN_IN.WITH_TWITTER.provider) {
                                            this.twitteSignIn();
                                        } else if (formType) {// BUT HERE I CAN'T SET THE formType FOR PASSWORD
                                            this.emailSignIn(values);
                                        }
                                    }
                                }}
                            >
                                {({ errors, handleBlur, handleChange, handleSubmit, isSubmitting, touched, values }) => (
                                    <form onSubmit={handleSubmit}>
                                        <Box mb={3}>
                                            <Typography color="textPrimary" variant="h2">
                                                Sign in
                                            </Typography>
                                            <Typography color="textSecondary" gutterBottom variant="body2">
                                                Sign in on the internal platform
                                            </Typography>
                                        </Box>
                                        <Grid container spacing={3}>
                                            <Grid item xs={12} md={6}>
                                                <Button
                                                    className={classes.facebook}
                                                    fullWidth
                                                    startIcon={<FacebookIcon />}
                                                    type="button"
                                                    onClick={this.submitFormType(SIGN_IN.WITH_FACEBOOK.provider, handleSubmit)}
                                                    size="large"
                                                    variant="contained"
                                                >
                                                    SIGN in with Facebook
                                                </Button>
                                            </Grid>
                                            <Grid item xs={12} md={6}>
                                                <Button
                                                    className={classes.google}
                                                    fullWidth
                                                    startIcon={<GoogleIcon />}
                                                    onClick={this.submitFormType(SIGN_IN.WITH_GOOGLE.provider, handleSubmit)}
                                                    size="large"
                                                    variant="contained"
                                                >
                                                    Sign in with Google
                                                </Button>
                                            </Grid>
                                            <Grid item xs={12} md={6}>
                                                <Button
                                                    className={classes.twitter}
                                                    fullWidth
                                                    startIcon={<TwitterIcon />}
                                                    onClick={this.submitFormType(SIGN_IN.WITH_TWITTER.provider, handleSubmit)}
                                                    size="large"
                                                    variant="contained"
                                                >
                                                    Sign in with Twitter
                                                </Button>
                                            </Grid>
                                        </Grid>
                                        <Box mt={3} mb={1}>
                                            <Typography align="center" color="textSecondary" variant="body1">
                                                or login with email address
                                            </Typography>
                                        </Box>
                                        <TextField
                                            error={Boolean(touched.email && errors.email)}
                                            fullWidth
                                            helperText={touched.email && errors.email}
                                            label="Email Address"
                                            margin="normal"
                                            name="email"
                                            onBlur={handleBlur}
                                            onChange={handleChange}
                                            type="email"
                                            value={values.email}
                                            variant="outlined"
                                        />
                                        <TextField
                                            error={Boolean(touched.password && errors.password)}
                                            fullWidth
                                            helperText={touched.password && errors.password}
                                            label="Password"
                                            margin="normal"
                                            name="password"
                                            onBlur={handleBlur}
                                            onChange={handleChange}
                                            type="password"
                                            value={values.password}
                                            variant="outlined"
                                        />
                                        <Box my={2}>
                                            <Button
                                                className={classes.button}
                                                disabled={isSubmitting}
                                                fullWidth
                                                size="large"
                                                type="submit"
                                                variant="contained"
                                                color="primary"
                                            >
                                                Sign in now
                                            </Button>
                                        </Box>
                                        <Typography color="textSecondary" variant="body1">
                                            Don&apos;t have an account?{' '}
                                            <Link color="textSecondary" component={RouterLink} to="../register" variant="h6">
                                                Sign up!
                                            </Link>
                                        </Typography>
                                    </form>
                                )}
                            </Formik>
                            <div>{isSavingRolesStarted ? <Dots /> : null}</div>
                            <h1 style={{ margin: '8px', color: 'red', textAlign: 'center', backgroundColor: 'white' }}>
                                {error && error.message}
                                {saveRolesErr && saveRolesErr.message}
                            </h1>
                        </Container>
                    </Box>
                </Page>
            </MotionDiv>
        );
    }
}

const mapDispatchToProps = dispatch => ({
    setUserRoleToUser: () => dispatch(changeToUserRole()),
});

const mapStateToProps = state => {
    return {
        isSavingRolesStarted: state.user.isSavingRolesStarted,
        saveRolesErr: state.user.saveRolesErrMsg,
    };
};
let LoginManagement = withStyles(useStyles)(LoginManagementBase);
const enhance = compose(withFirebase, connect(mapStateToProps, mapDispatchToProps), withEmailVerification);

LoginManagement = enhance(LoginManagement);

const LoginView = () => (
    <AuthUserContext.Consumer>
        {authUser => (
            <div>
                <LoginManagement authUser={authUser} />
            </div>
        )}
    </AuthUserContext.Consumer>
);

const condition = authUser => authUser && authUser.roles.includes(ROLES.ANON);
export default withAuthorization(condition)(LoginView);
EN

回答 1

Stack Overflow用户

发布于 2020-12-22 02:23:16

我现在不能解决这个问题,所以我暂时做了香草反应。

代码语言:javascript
运行
复制
import React from 'react';
import { connect } from 'react-redux';
import { compose } from 'recompose';
import { Link as RouterLink } from 'react-router-dom';
import { Box, Button, Container, Grid, Link, TextField, Typography } from '@material-ui/core';
import { withStyles } from '@material-ui/core/styles';
import Dots from 'react-activity/lib/Dots';
import { withFirebase } from '../../../../firebase';
import FacebookIcon from '../../../../assets/Facebook';
import GoogleIcon from '../../../../assets/Google';
import TwitterIcon from '../../../../assets/twitter-logo';
import Page from '../../utils/Page';
import MotionDiv from '../../utils/MotionDiv';
import { withEmailVerification, withAuthorization, AuthUserContext } from '../../../../session';
import { changeToUserRole } from '../../../../redux/userData/user.actions';
import * as ROLES from '../../../../constants/roles';
import 'react-activity/lib/Dots/Dots.css';
import * as SIGN_IN from '../../../../constants/signinmethods';

const useStyles = theme => ({
    root: {
        backgroundColor: theme.palette.primary.light,
        minHeight: '100vh',
        paddingBottom: theme.spacing(3),
        paddingTop: theme.spacing(3),
    },
    container: {
        backgroundColor: theme.palette.primary.main,
        paddingTop: theme.spacing(3),
    },
    textField: {
        boxShadow: theme.shadows[3],
        backgroundColor: theme.palette.primary.light,
    },
    facebook: {
        backgroundColor: '#3b5999',
        color: 'white',
        '&:hover': {
            backgroundColor: '#4d70ba',
        },
    },
    google: {
        backgroundColor: '#ffffff',
        textColor: 'black',
    },
    twitter: {
        backgroundColor: '#ffffff',
        textColor: 'black',
    },
    signInButton: {
        backgroundColor: theme.palette.primary.main,
        boxShadow: theme.shadows[5],
    },
});

const INITIAL_EMAIL_STATE = {
    email: '',
    password: '',
    error: null,
    message: '',
    isSubmitting: false,
};

class LoginManagementBase extends React.Component {
    constructor() {
        super();
        this.state = {
            ...INITIAL_EMAIL_STATE,
        };
        this.facebookSignIn = this.facebookSignIn.bind(this);
        this.googleSignIn = this.googleSignIn.bind(this);
        this.twitteSignIn = this.twitteSignIn.bind(this);
    }

    onSocialLoginLink = provider => {
        const { firebase, setUserRoleToUser } = this.props;
        firebase.auth.currentUser
            .linkWithPopup(firebase[provider])
            .then(res => {
                if (res.credential) {
                    if (res.user.email) {
                        firebase.doLogEvent(`linkWithPopup to Firestore for: ${res.user.email}`);
                    } else {
                        firebase.doLogEvent(`linkWithPopup to Firestore for: ${res.credential.providerId}`);
                    }
                    setUserRoleToUser();
                }
            })
            .then(this.fetchSignInMethods)
            .catch(error => {
                if (error.code === 'auth/credential-already-in-use') {
                    const anonUser = firebase.auth.currentUser;
                    firebase.auth
                        .signInWithCredential(error.credential)
                        .then(res => {
                            if (res.user.email) {
                                firebase.doLogEvent(`signInWithCredential to Firestore for: ${res.user.email}`);
                            } else {
                                firebase.doLogEvent(`signInWithCredential to Firestore for: ${res.credential.providerId}`);
                            }
                            setUserRoleToUser();
                            // remove the anonUser implications?
                            // TODO: As anonymouse the User can't change the content(viewer only) so removing should not be a problem
                            anonUser
                                .delete()
                                .then(() => {
                                    firebase.doLogEvent(`Deleted anonUser when signing in`);
                                })
                                .catch(err => {
                                    firebase.doLogEvent(`Error deleted anonUser when signing in: ${err}`);
                                    firebase.doLogEvent(`Manually remove anon account: ${anonUser.uid}`);
                                });
                        })
                        .catch(error => {
                            this.setState({ error, isSubmitting: false });
                        });
                } else if (error.code === 'auth/email-already-in-use') {
                    error.message = `The email address ${error.email} is already in use by another account.`;
                    this.setState({ error, isSubmitting: false });
                } else {
                    this.setState({ error, isSubmitting: false });
                }
            });
    };

    googleSignIn = () => {
        this.setState({
            isSubmitting: true,
        });
        this.onSocialLoginLink(SIGN_IN.WITH_GOOGLE.provider);
    };

    facebookSignIn = () => {
        this.setState({
            isSubmitting: true,
        });
        this.onSocialLoginLink(SIGN_IN.WITH_FACEBOOK.provider);
    };

    twitteSignIn = () => {
        this.setState({
            isSubmitting: true,
        });
        this.onSocialLoginLink(SIGN_IN.WITH_TWITTER.provider);
    };

    emailSignIn = () => {
        const { email, password } = this.state;
        const { firebase } = this.props;

        firebase.auth
            .signInWithEmailAndPassword(email, password)
            .then(() => {
                this.setState({ ...INITIAL_EMAIL_STATE });
                // this.props.history.push(ROUTES.HOME);
            })
            .catch(error => {
                this.setState({ error, isSubmitting: false });
            });
    };

    mailHandle = e => {
        const mailValue = e.target.value;
        this.setState({
            email: mailValue,
        });
    };

    passwordHandle = e => {
        const passwordValue = e.target.value;
        this.setState({
            password: passwordValue,
        });
    };

    chekvalid = () => {
        const { email, password } = this.state;
        const isEmailValid = this.ValidEmail(email);
        const isPasswordValid = this.ValidPass(password);
        if (password.length === 0 && email.length === 0) {
            this.setState({
                error: 'Enter E-Mail and Password to continue!',
            });
        }
        if (!isPasswordValid) {
            this.setState({
                message: 'Password should have more then 5 character',
            });
        }
        if (email.length === 0) {
            this.setState({
                message: 'Enter an E-Mail to continue!',
            });
        }
        if (password.length === 0) {
            this.setState({
                message: 'Enter an Password to continue!',
            });
        }
        if (!isEmailValid) {
            this.setState({
                message: 'E-Mail is not valid!',
            });
        }
        if (isEmailValid && isPasswordValid) {
            this.setState({
                message: '',
                isSubmitting: true,
            });
            this.emailSignIn();
        }
    };

    ValidEmail = email => {
        const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        return re.test(String(email).toLowerCase());
    };

    ValidPass = email => {
        if (email.length > 5) {
            return true;
        }
        return false;
    };

    render() {
        const { classes } = this.props;
        const { message, error, email, password, isSubmitting } = this.state;
        const { saveRolesErr, isSavingRolesStarted } = this.props;
        if (error && error.message) {
            console.log(error.message);
        }
        return (
            <MotionDiv>
                <Page className={classes.root} title="Sign In">
                    <Box display="flex" flexDirection="column" height="100%" justifyContent="center">
                        <Container maxWidth="sm" className={classes.container}>
                            <Box mb={3}>
                                <Typography color="textPrimary" variant="h2">
                                    Sign in
                                </Typography>
                                <Typography color="textSecondary" gutterBottom variant="body2">
                                    Sign in on the internal platform
                                </Typography>
                            </Box>
                            <Grid container spacing={3}>
                                <Grid item xs={12} md={6}>
                                    <Button
                                        className={classes.facebook}
                                        disabled={isSubmitting}
                                        fullWidth
                                        startIcon={<FacebookIcon />}
                                        type="submit"
                                        onClick={this.facebookSignIn}
                                        size="large"
                                        variant="contained"
                                    >
                                        SIGN in with Facebook
                                    </Button>
                                </Grid>
                                <Grid item xs={12} md={6}>
                                    <Button
                                        className={classes.google}
                                        disabled={isSubmitting}
                                        fullWidth
                                        type="submit"
                                        startIcon={<GoogleIcon />}
                                        onClick={this.googleSignIn}
                                        size="large"
                                        variant="contained"
                                    >
                                        Sign in with Google
                                    </Button>
                                </Grid>
                                <Grid item xs={12} md={6}>
                                    <Button
                                        className={classes.twitter}
                                        disabled={isSubmitting}
                                        fullWidth
                                        type="submit"
                                        startIcon={<TwitterIcon />}
                                        onClick={this.twitteSignIn}
                                        size="large"
                                        variant="contained"
                                    >
                                        Sign in with Twitter
                                    </Button>
                                </Grid>
                            </Grid>
                            <Box mt={3} mb={1}>
                                <Typography align="center" color="textSecondary" variant="body1">
                                    or login with email address
                                </Typography>
                            </Box>
                            <form noValidate autoComplete="off">
                                <TextField
                                    className={classes.textField}
                                    variant="outlined"
                                    margin="normal"
                                    required
                                    fullWidth
                                    id="email"
                                    label="Email Address"
                                    name="email"
                                    autoComplete="email"
                                    value={email}
                                    onChange={this.mailHandle}
                                    color="secondary"
                                />
                            </form>
                            <form noValidate autoComplete="off">
                                <TextField
                                    className={classes.textField}
                                    variant="outlined"
                                    margin="normal"
                                    required
                                    fullWidth
                                    name="password"
                                    label="Password"
                                    type="password"
                                    id="password"
                                    autoComplete="current-password"
                                    value={password}
                                    onChange={this.passwordHandle}
                                    color="secondary"
                                />
                            </form>
                            <Box my={2}>
                                <Button
                                    disabled={isSubmitting}
                                    className={classes.signInButton}
                                    fullWidth
                                    size="large"
                                    type="submit"
                                    variant="contained"
                                    color="primary"
                                    onClick={this.chekvalid}
                                >
                                    Sign in now
                                </Button>
                            </Box>
                            <Typography color="textSecondary" variant="body1">
                                Don&apos;t have an account?{' '}
                                <Link color="textSecondary" component={RouterLink} to="../register" variant="h6">
                                    Sign up!
                                </Link>
                            </Typography>

                            <div>{isSavingRolesStarted ? <Dots /> : null}</div>
                            <h1 style={{ margin: '8px', color: 'red', textAlign: 'center', backgroundColor: 'white' }}>
                                {message}
                                {error && error.message}
                                {saveRolesErr && saveRolesErr.message}
                            </h1>
                        </Container>
                    </Box>
                </Page>
            </MotionDiv>
        );
    }
}

const mapDispatchToProps = dispatch => ({
    setUserRoleToUser: () => dispatch(changeToUserRole()),
});

const mapStateToProps = state => {
    return {
        isSavingRolesStarted: state.user.isSavingRolesStarted,
        saveRolesErr: state.user.saveRolesErrMsg,
    };
};
let LoginManagement = withStyles(useStyles)(LoginManagementBase);
const enhance = compose(withFirebase, connect(mapStateToProps, mapDispatchToProps), withEmailVerification);

LoginManagement = enhance(LoginManagement);

const LoginView = () => (
    <AuthUserContext.Consumer>
        {authUser => (
            <div>
                <LoginManagement authUser={authUser} />
            </div>
        )}
    </AuthUserContext.Consumer>
);

const condition = authUser => authUser && authUser.roles.includes(ROLES.ANON);
export default withAuthorization(condition)(LoginView);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65382931

复制
相关文章

相似问题

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