Getting URL Parameters on GatsbyJS

Lex picture Lex · Dec 16, 2018 · Viewed 10.1k times · Source

Is there a way to retrieve url parameters passed on pages of project built on GatsbyJS? I'm trying to implement a password reset function on my page using AWS, but they can only send the parameters through a link sent to the user's email.

So the flow would be like this :

User triggers Forgot Password -> AWS sends email to user with link -> Link directs to my page with the parameters -> Reset password form automatically populates fields with the parameters passed

Update

Here's my App.js code :

import { Router } from "@reach/router"


const App = () => (
  <Layout>
    <Router>
      <Login path="signin" exact component={Login} />
      <Resources path="api/resources" exact component={Resources} />
      <Verify path="verify" exact component={Verify} />
      <Forgot path="forgot" exact component={Forgot} />
      <Reset path="account/reset/:code" exact component={Reset}/>
    </Router>
  </Layout>
)

export default App;

Reset.js :

export default class ResetForm extends Component {
    constructor(props) {
        super(props);

        this.state = {
            password: "",
            confirmPassword: "",
            vercode: "",
            email: "",
            emailValid: false,
            passValid: false,
            confirmValid: false,
            codeValid: false,
            formValid: true,
            formErrors : {
                email: false,
                password: false,
                confirmPassword: false,
                vercode: false,
            },
            respErrors : {
                email: {
                    isValid : true,
                    message : ""
                },
                password: {
                    isValid : true,
                    message : ""
                },
                code : {
                    isValid : true,
                    message : ""
                }
            }

        };

    }

    validateField(field, value) {

        let password = this.state.password
        let fieldValidationErrors = this.state.formErrors;
        let emailValid = this.state.emailValid
        let passValid = this.state.passValid
        let confirmValid = this.state.confirmValid
        let codeValid = this.state.vercode
        let fieldValidationMessages = this.state.respErrors;


        switch(field){
            case 'email' :
                emailValid = validator.isEmail(value);
                fieldValidationErrors.email = emailValid ? false : true;
                fieldValidationMessages.email.isValid = true;
                fieldValidationMessages.email.message = "Invalid E-Mail Address";
                break;

            case 'password' :
                passValid = validator.matches(value, RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*])(?=.{8,})'));

                fieldValidationMessages.password.message = passValid ? '' : undefined;

                if(!validator.matches(value,RegExp('^(?=.*[a-z])(?=.*[A-Z])'))){
                    fieldValidationMessages.password.message = "At least 1 Upper case character is required";
                }

                if(!validator.matches(value,RegExp('^(?=.*[!@#$%^&*])'))){
                    fieldValidationMessages.password.message = "At least 1 Symbol is required";
                }

                if(!validator.matches(value,RegExp('^(?=.{8,})'))){
                    fieldValidationMessages.password.message = "Password must have at least 8 characters";
                }


                fieldValidationErrors.password = passValid ? false : true;
                break;

            case 'confirmPassword' :
                confirmValid = validator.equals(value, password);
                fieldValidationErrors.confirmPassword = confirmValid ? false : true;
                break;

            case 'vercode' :
                codeValid = !validator.isEmpty(value);
                fieldValidationErrors.vercode = codeValid ? false : true;
                break;

            default :

                break
            }

        this.setState({
            formErrors: fieldValidationErrors,
            emailValid: emailValid,
            passValid: passValid,
            confirmValid: confirmValid,
            codeValid: codeValid,
        }, this.validateForm())

    }

    validateForm(){
        this.setState({
            formValid: 
                this.state.emailValid && this.state.confirmValid && this.state.codeValid && this.state.passValid
        })

    }

    handleChange = event => {
        const name = event.target.id;
        const value = event.target.value;
        this.setState({
            [name]: value
        },
            () => {
                this.validateField(name, value)
            }
        );
    }


    handleSubmit = async (event) => {
        event.preventDefault()
        const state = this.state

        await handleReset(state)
        .then(async (data) => {
            if(data.isValid){
                await handleLogin(state)
                .then(() => {
                    navigate('/')
                })
                .catch(err => console.log(err))
            } else {
                switch (data.code) {
                    case CODE_RESET.RESET_EXPIRED:
                        data.message = "The verification code you have submitted is already expired."
                        break
                    case CODE_RESET.RESET_MISMATCH:
                        data.message = "The verification code you have submitted is invalid."
                        break

                    default:
                        data.message = "Something went wrong."
                        break;
                }

                this.setState({
                    [state.respErrors.code.isValid] : data.isValid,
                    [state.respErrors.code.message] : data.message
                })
            }
        })
        .catch(async(err) => {
            console.log(err)
        })

    }

  render() {
        if(isLoggedIn()) {
            navigate(`/`)
        }

        return (

            <Row className={[formStyles.formContainer, "row"].join(' ')} >
            <Col sm={{
                size:12
                }}
                md={{
                    size: 8,
                    offset: 2
                }}
            >
                <Form 
                    onSubmit={this.handleSubmit} 
                >
                    <h3 style={{
                        fontWeight: 'bolder'
                    }}>
                        Reset Password
                    </h3>
                    <FormGroup>
                        <Label for="email">Email</Label>
                        <Input
                            id="email"
                            autoFocus
                            type="email"
                            name="email"
                            value={this.state.email.value}
                            onChange={this.handleChange}
                            className={formStyles.signUp} 
                            valid={this.state.emailValid}
                            invalid={(this.state.formErrors.email || !this.state.respErrors.email.isValid ) ? true : undefined}
                        />
                        <FormFeedback invalid={this.state.respErrors.email.isValid ? '' : undefined}>
                            {this.state.respErrors.email.message}
                        </FormFeedback>
                    </FormGroup>

                    <FormGroup>
                        <Label for="password">New Password</Label>
                        <Input
                            id="password"
                            type="password"
                            name="password"
                            value={this.state.password.value}
                            onChange={this.handleChange}
                            className={formStyles.signUp} 
                            valid={this.state.passValid }
                            invalid={this.state.formErrors.password ? true : undefined}
                        />
                        <FormText invalid={this.state.respErrors.password.isValid ? '' : undefined}>
                            {this.state.respErrors.password.message}

                        </FormText>
                    </FormGroup>
                    <FormGroup>
                        <Label for="confirmPassword">Confirm Password</Label>
                        <Input
                            id="confirmPassword"
                            type="password"
                            name="confirmPassword"
                            value={this.state.confirmPassword.value}
                            onChange={this.handleChange}
                            className={formStyles.signUp}
                            valid={this.state.confirmValid }
                            invalid={this.state.formErrors.confirmPassword ? true : undefined}
                        />
                        <FormFeedback
                            invalid={this.state.formErrors.confirmPassword ? '' : undefined}
                        >
                            Password does not match    
                        </FormFeedback>

                    </FormGroup>

                    <FormGroup>
                        <Label for="vercode">Verification Code</Label>
                        <Input
                            id="vercode"
                            type="text"
                            name="vercode"
                            maxLength={6}
                            value={this.state.vercode.value}
                            onChange={this.handleChange}
                            className={formStyles.signUp} 
                            valid={this.state.codeValid.value }
                            invalid={this.state.formErrors.vercode || !this.state.respErrors.code.isValid ? true : undefined}
                        />
                        <FormFeedback invalid={this.state.respErrors.code.isValid ? '' : undefined} >
                            {this.state.respErrors.code.message}
                        </FormFeedback>
                    </FormGroup>

                    <Button 
                        color="primary"
                        disabled={!this.state.formValid}
                    >
                        Submit
                    </Button>
                </Form>
            </Col>
      </Row>
    )
  }
}

Answer

pungggi picture pungggi · Jan 12, 2019

Use props.location, introduced in Gatsby v2. It's made available by @reach/router to all components via props.

function Component(props) {
  // use props.location...
  return ...
}