对应内容:#13 Hitting the API | Build a Complete App with GraphQL, Node.js, MongoDB and React.js
主要内容:
- 完成登录、注册表单,及其对应的逻辑
- 由于涉及前后端的通信,在后端实现跨域的中间件【及其重要】
1 完成表单部分的页面及其对应逻辑,修复了前面的BUG
这里ES6中的类,很多人不是很熟悉,类的属性的实现方式分两种,一种是写在constructor中的属性,一种是类字段,定义在构造函数之外的,类字段是直接赋值在类的对象实例上的,而普通属性是写在类的原型上的,因此类字段声明的函数表达式,是不需要进行this绑定的,在react官方文档中,明确说明了class 中声明的函数,要在构造函数中绑定一下this,这里要注意!!!!
这里用的是ref进行绑定,而没有使用官方文档中的setState,第二种写起来比较麻烦。
import React, { Component } from 'react';
import './Auth.css';
class AuthPage extends Component {
constructor (props) {
super(props);
this.emailEl = React.createRef();
this.passwordEl = React.createRef();
this.state = {
isLoginMode: true
}
}
submitHandler = async (event) => {
event.preventDefault();
let email = this.emailEl.current.value;
let password = this.passwordEl.current.value;
if (email.trim() === "" || password.trim() === "") {
return false;
}
const requestBody = {
query: `
mutation {
createUser(userInput: {email: "${email}", password: "${password}"}) {
_id
email
}
}
`
};
if (this.state.isLoginMode) {
requestBody.query = `
query {
login(email: "${email}", password: "${password}") {
_id
token
tokenExpiration
}
}
`;
}
let response, data;
try {
response = await fetch(`http://localhost:3030/graphql`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(requestBody)
});
data = await response.json();
} catch (error) {
throw error;
}
}
swithHandler = () => {
this.setState(prevState => {
return {
isLoginMode: !prevState.isLoginMode
};
})
}
render () {
return (
<React.Fragment>
<h1>The Auth Page</h1>
<form action="" className="auth-form" onSubmit={ this.submitHandler }>
<div className="form-control">
<label htmlFor="email">Email</label>
<input type="email" id="email" ref={this.emailEl} />
</div>
<div className="form-control">
<label htmlFor="password">Password</label>
<input type="password" id="password" ref={this.passwordEl} />
</div>
<div className="form-action">
<button type="submit">Submit</button>
<button type="button" onClick={this.swithHandler}>
swith to {this.state.isLoginMode ? "Signup" : "Signin"}
</button>
</div>
</form>
</React.Fragment>
);
}
}
export default AuthPage;
Auth.css
.auth-form {
width: 300px;
margin: 1rem auto;
}
label, input {
display: block;
width: 100%;
}
.form-action button {
font: inherit;
}
在后端的auth resolver中我之前的代码有一个bug,在这里进行修复:
第四行那里少了一个await,并且稍微修改了一些逻辑
2 后端实现跨域中间件
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type,Authorization");
if (req.method === "OPTIONS") {
return res.sendStatus(200);
}
next();
})
具体原因,一行两行说不清楚,请在mdn中搜索cors或跨越。