yarn dev运行后端代码,再回到前端代码,yarn start运行就能获取到数据了,
因为在package.json中proxy设置了端口3001
Handling Login
App.js添加登录表单
const App = () => {-- snip --const [username, setUsername] = useState('')const [password, setPassword] = useState('')useEffect(() => {noteService.getAll().then(initialNotes => {setNotes(initialNotes)})}, [])// ...const handleLogin = (event) => {event.preventDefault()console.log('logging in with', username, password)}return (<div><h1>Notes</h1><Notification message={errorMessage} /><form onSubmit={handleLogin}><div>username<inputtype="text"value={username}name="Username"onChange={({ target }) => setUsername(target.value)}/></div><div>password<inputtype="password"value={password}name="Password"onChange={({ target }) => setPassword(target.value)}/></div><button type="submit">login</button></form>// ...</div>)}export default App
注意input元素中事件的写法
<inputtype="text"value={username}name="Username"onChange={({ target }) => setUsername(target.value)}/>
target是input元素本身,加{}转化为对象
以上写法等价于
<inputtype="text"value={username}name="Username"onChange={( event ) => setUsername(event.target.value)}/>
添加services/login.js模块
import axios from 'axios'const baseUrl = '/api/login'const login = async credentials => {const response = await axios.post(baseUrl, credentials)return response.data}export default { login }
实现登录功能
import loginService from './services/login'const App = () => {// ...const [user, setUser] = useState(null)// ...const handleLogin = async (event) => {event.preventDefault()try {const user = await loginService.login({username, password})setUser(user)setUsername('')setPassword('')} catch (exception) {setErrorMessage('Wrong credentials')setTimeout(() => {setErrorMessage(null)}, 5000)}}// ...}
按条件渲染表单
当用户未登录时才显示登录表单
在App组件中添加2个辅助函数, 返回值是JSX
const App = () => {// ...const loginForm = () => (<form onSubmit={handleLogin}>// ...</form>)const noteForm = () => (<form onSubmit={addNote}>// ...</form>)return (// ...)}
按条件渲染
const App = () => {// ...const loginForm = () => (// ...)const noteForm = () => (// ...)return (<div>// ...{user === null && loginForm()}{user !== null && noteForm()}// ...</div>)}
还可以使用三元运算符
{user === null ?loginForm() :<div><p>{user.name} logged-in</p>{noteForm}</div>}
Creating new notes
修改services/notes.js, create时将token传入
import axios from 'axios'const baseUrl = '/api/notes'let token = nullconst setToken = newToken => {token = `bearer ${newToken}`}const getAll = () => {const request = axios.get(baseUrl)return request.then(response => response.data)}const create = async newObject => {const config = {headers: { Authorization: token },}const response = await axios.post(baseUrl, newObject, config)return response.data}const update = (id, newObject) => {const request = axios.put(`${ baseUrl } /${id}`, newObject)return request.then(response => response.data)}export default { getAll, create, update, setToken }
登录时设置token的值
const handleLogin = async (event) => {event.preventDefault()try {const user = await loginService.login({username, password,})noteService.setToken(user.token)setUser(user)setUsername('')setPassword('')} catch (exception) {// ...}}
Saving the token to browsers local storage
当页面重新渲染时user信息就没了,可以将用户信息存入localStorage
window.localStorage.setItem('name', 'juha tauriainen') // 存入window.localStorage.getItem('name') // 读取window.localStorage.removeItem('name') // 删除window.localStorage.clear() // 清空
存储到本地存储的值称为DOMstrings,所以我们不能存储一个 Javascript 对象。
修改登录方法:
const handleLogin = async (event) => {event.preventDefault()try {const user = await loginService.login({username, password,})window.localStorage.setItem('loggedNoteappUser', JSON.stringify(user))noteService.setToken(user.token)setUser(user)setUsername('')setPassword('')} catch (exception) {// ...}}
在控制台查看localStorage
使用Effect hook, 加载页面时读取user信息
const App = () => {// ...useEffect(() => {const loggedUserJSON = window.localStorage.getItem('loggedNoteappUser')if (loggedUserJSON) {const user = JSON.parse(loggedUserJSON)setUser(user)noteService.setToken(user.token)}}, [])// ...}
Exercise 5.1 - 5.4
克隆代码,安装依赖
git clone https://github.com/fullstack-hy/bloglist-frontendnpm installnpm start
get传递token
// ...let token = nullconst setToken = newToken => {token = `bearer ${newToken}`}const getAll = async () => {const config = {headers: { Authorization: token }}const response = await axios.get(baseUrl, config)return response.data}// ...
编写事件处理函数时,别忘了event.preventDefault()
如果要获取get或post之后的数据,别忘了要用async/await, 否则得到的是undefined
const createBlog = async (event) => {event.preventDefault()try {const newBlog = await blogService.create(blog)setBlogs(blogs.concat(newBlog))} catch (error) {console.log(error)}setBlog({'title': '','author': '','url': ''})}
