在 GatsbyJS 上获取 URL 个参数
Getting URL Parameters on GatsbyJS
有没有办法检索在基于 GatsbyJS 的项目页面上传递的 url 参数?
我正在尝试使用 AWS 在我的页面上实现密码重置功能,但他们只能通过 link 将参数发送到用户的电子邮件。
所以流程是这样的:
用户触发忘记密码 -> AWS 使用 link 向用户发送电子邮件 -> Link 使用参数定向到我的页面 -> 重置密码表单自动使用传递的参数填充字段
更新
这是我的 App.js 代码:
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>
)
}
}
使用props.location
, introduced in Gatsby v2。 @reach/router 通过 props
.
将其提供给所有组件
function Component(props) {
// use props.location...
return ...
}
按照 MDN 中的说明使用 URLSearchParams.get()
:
// Get the location object that is implicitly passed as props
// for every page in the `pages` folder
const Index = ({ location }) => {
console.log(location); // inspect location for yourself
// the parameter to return for URL. Example:
// https://localhost:8000/?parameter1=firstParam¶meter2=secondParam
const params = new URLSearchParams(location.search);
const parameter1 = params.get("parameter1");
const parameter2 = params.get("parameter2");
console.log(parameter1); // -> "firstParam"
console.log(parameter2); // -> "secondParam"
// ...
备选方案:包 query-string
yarn add query-string
或 npm i --save query-string
import * as queryString from "query-string";
// Get the location object that is implicitly passed as props
// for every page in the `pages` folder
const Index = ({ location }) => {
console.log(location); // inspect location for yourself
// query-string parses the parameters that are contained in the location object
const { parameter1, parameter2 } = queryString.parse(location.search);
console.log(parameter1);
console.log(parameter2);
// ...
有没有办法检索在基于 GatsbyJS 的项目页面上传递的 url 参数? 我正在尝试使用 AWS 在我的页面上实现密码重置功能,但他们只能通过 link 将参数发送到用户的电子邮件。
所以流程是这样的:
用户触发忘记密码 -> AWS 使用 link 向用户发送电子邮件 -> Link 使用参数定向到我的页面 -> 重置密码表单自动使用传递的参数填充字段
更新
这是我的 App.js 代码:
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>
)
}
}
使用props.location
, introduced in Gatsby v2。 @reach/router 通过 props
.
function Component(props) {
// use props.location...
return ...
}
按照 MDN 中的说明使用 URLSearchParams.get()
:
// Get the location object that is implicitly passed as props
// for every page in the `pages` folder
const Index = ({ location }) => {
console.log(location); // inspect location for yourself
// the parameter to return for URL. Example:
// https://localhost:8000/?parameter1=firstParam¶meter2=secondParam
const params = new URLSearchParams(location.search);
const parameter1 = params.get("parameter1");
const parameter2 = params.get("parameter2");
console.log(parameter1); // -> "firstParam"
console.log(parameter2); // -> "secondParam"
// ...
备选方案:包 query-string
yarn add query-string
或 npm i --save query-string
import * as queryString from "query-string";
// Get the location object that is implicitly passed as props
// for every page in the `pages` folder
const Index = ({ location }) => {
console.log(location); // inspect location for yourself
// query-string parses the parameters that are contained in the location object
const { parameter1, parameter2 } = queryString.parse(location.search);
console.log(parameter1);
console.log(parameter2);
// ...