Reacthooks作为一个比较新的React特性,一定程度上是对React做了一次较大程度的更新,在很多方向都给React的写法提供了新的思路,这里举个小例子:
/*
* @Date: 2019-10-15 10:31:13
* @LastEditors: Asen Wang
* @LastEditTime: 2019-10-15 10:54:25
* @content: I
*/
import React, {useState} from 'react';
const Xiaojiejie = ()=> {
const [age, setAge] = useState(18)
const [name, setName] = useState('xing')
return (
<div>
<span>{age} </span>
<span>{name}</span>
<button onClick={()=>{setAge(age+1); setName(name.replace('ng','gn'))}}>click</button>
</div>
)
}
export default Xiaojiejie
这是一个绑定点击事件的小例子,用Hooks写成,以前的写法就不贴了,熟悉的小伙伴肯定能一下看出来这样的写法比原来的面向对象的写法更加简洁。
目录
生命周期
关于生命周期函数在Hooks中的使用,我们先看原来一些生命周期的钩子函数的写法,如:
componentDidMount() {}
componentDIdUpdate() {}
在Hooks写法中也有更简洁的表现:
useEffect(()=>{
console.log('start')
})
这里包含了上面commponentDidMount()和componentUpdate()的全部功能,但注意这时异步的。
关于如何解绑的问题,Hooks提供了使用返回值来解绑的方法,如下面这个小示例:
const Home = () => {
useEffect(() => {console.log('come');
return () => {
console.log('leave')
}
})
return (
<h2>Home</h2>
)
}
const About = () => (
<h2>About</h2>
)
...
<Router>
<ul>
<li><Link to='/'>首页</Link></li>
<li><Link to='/about'>关于作者</Link></li>
</ul>
<Route path='/' exact component={Home} />
<Route path='/about' component={About} />
</Router>
...
我们实现了两个页面的路由跳转,当我们跳转到About页面的时候,就会发现控制台能打印出"leave"的字样,说明我们实现了解绑的方法,但是注意的是这样做还是有些不对劲,当我们和之前的点击事件一起使用时发现,只要我们点击click按钮,页面发生更新,那么leave也会被执行一遍。
那么如何解决这个问题呢,我们其实只要给useEffect设置一个监听方法即可,对于这个应用,我们直接传个空数组,代表当我们销毁组件时这个return方法才会被返回。当然如果有值的话也可以传值,监听这个值的变化来决定return后的这个生命周期函数方法是否执行。
父子组件传值
先说一个坑,贴Demo:
import React, {useState, createContext, useContext} from 'react';
const CountContext = createContext()
const Counter = () => {
let age = useContext(CountContext)
return(
<h2>{{age}}</h2>
)
}
const addAge= ()=> {
const [age, setAge] = useState(18)
return (
<div>
<span>{age} </span>
<button onClick={()=>{setAge(age+1)}}>click</button>
<CountContext.Provider value={age}>
<Counter/>
</CountContext.Provider>
</div>
)
}
export default addAge
这是一个经典的父子组件传值的任务,但是会报错:
Objects are not valid as a React child (found: object with keys {age}). If you meant to render a collection of children, use an array instead.
因为之前我写父子组件拆分到了两个文件,于是踩坑开始了,报错内容牵扯到了React.dom里面的内容,于是我还以为是组件的导入导出出现了错误,把export和import又查了一遍发现没错啊。
于是我把两个组件合并成上面的格式,还是找不到出错的地方。
细心的小伙伴可能已经看到了,报错里面其实写的很清楚了,可我就是没注意到,没错习惯NG的我居然把{}写成了{{}},最后修改之后果然一切安好。
父子组件传值是比较基础的内容,掌握好useContext和creatContext即可,下面我们要讲的状态管理区reducer分开即可,两者结合更像Redux的东西。
UseReducer
还是一个小demo来看一下什么是UseReducer,很简单,先不和useContext结合使用:
/*
* @Date: 2019-10-15 10:31:13
* @LastEditors: Asen Wang
* @LastEditTime: 2019-10-15 10:54:25
* @content: I
*/
import React, {useReducer} from 'react';
const Demo = () => {
const [count, dispatch] = useReducer((state, action)=>{
switch (action) {
case 'add':
return state+1
case 'sub':
return state-1
default:
return state
}
}, 0)
return (
<div>
<h2>{count}</h2>
<button onClick={()=>{dispatch('add')}}>increase</button>
<button onClick={()=>{dispatch('sub')}}>decrease</button>
</div>
)
}
export default Demo
个人感觉写起来确实思路很明确,这种结构个人感觉比Vue舒服。
先到这儿,下一篇再讲怎么实现类似Redux的效果。