需求描述:
在本项目之前,公司项目均采用的是Vue技术栈,根据公司,前端组以及个人需求等最终得出技术栈将慢慢迁移到React
技术栈:
本项目仅采用了react hooks 以及 fetch.js 还有很多第三方库包,未曾涉及到redux
react hooks:
虽说现在网上有很多关于react hooks的一些文章,但是我还是想写写,一呢是想加深印象,二呢是想知道自己理解的东西和别人理解的不一样的地方。 首先我们来理解一下什么是hooks: 相信大家在react hooks发布之前都会使用到class components(类组件), 以及 function components(无状态组件)
// 类组件
class App extends React.Component {
constructor(props){
super(props);
this.state = {
name: 'dengpeng'
}
}
render() {
return (<Foo name={this.state.name}/>);
}
}
// 无状态组件
function Foo(props) {
const { name } = props;
return (<div>{name}</div>);
}
在之前function components(无状态组件)里面是无法法使用 react 生命周期的,所以在Hooks发布后这类组件,便被称为“函数组件(FC)”了,因为可以在里面使用Hooks了,比如:
function Bar() {
// hooks
const [name, setName] = useState('dengpeng');
return (<div>{name}</div>);
}
那么Hooks到底是什么呢? Hooks 就是一个特殊的钩子函数,用于将react的特性加入到FC里来,比如useState,他就是允许在React FC中添加state的Hook。
useState 这是react hooks最最常用的3大hooks之一 useState,那么他到底是什么呢? useState: 一呢声明了state变量以及操作state的方法,比如上面的例子。 useState参数:它接收一个参数,就是声明的这个state的初始值 useState返回值:他返回一个数组,数组里有2个对象,一呢是state变量,二呢就是state方法,如果你要修改state值,就会使用这个方法。 比如:
// 读取state数据 const [name, setName] = useState('dengpeng'); return <div>读取name: {name}</div>; // 修改state数据 <button onClick={() => setName('caipeiyi')} >修改name</button>;
useEffect 这是react hooks最最常用的3大hooks之一 useEffect,那么他到底是什么呢? 相传useEffect 结合了类组件的3大生命周期集一身,componentDidUpdate(cDU), componentDidMount(cDM), componentWillUnmount(cWU),他为何如此之吊。我也不知道!!这也许就是react魅力之处吧,至从16.8更新以来,惊喜不断呀!!!!! 在之前类组件的时候,常见操作组件的方式需要清除某些东西cWU和不需要清除cDU,那么useEffect如何实现这个功能的呢,源码我们就不看了,看个例子就行了。
// exmp1 useEffect(() => { document.title = '邓鹏博客' }, []) // exmp2 useEffect(() => { const query = location.search.query; document.title = '邓鹏博客' + query }, [query]) // exmp3 useEffect(() => { document.title = '邓鹏博客' }) useEffect(() => { let timer = setInterval(() => { console.log(11111); }, 1000) return () => { clearInterval(timer); } })
如上有3个例子:useEffect 可接收2个参数,其中第一个参数是一个函数(required),第二个参数(非必要参数)就非常厉害了,是一个依赖数组。 exmp1: 第二个参数是一个空数组,代表着当前useEffect 不需要依赖某项而发生变化,意味着只会执行一次,就是cDM exmp2: 第二个参数易依赖于query,代表着当前仅当query值发生变化的时候,useEffect的第一个参数函数才会重新执行一次,就是cDU; exmp3: 第二个参数被省略了,代表着只要当前组件的任意项,发生变化则该函数都会执行一次(最好不要这样) exmp4: 该例子不是看参数是什么,是看第一个参数函数的return,返回一个函数,该函数就是在组件卸载的时候需要清除的东西, 就是cWU;
useContext 这是react hooks最最常用的3大hooks之一 useContext,那么他到底是什么呢? 他就是react 关联上下文的一个Hooks,旨在便捷组件内部通信,不用组件之间层级传递props 在16.8之前,react是如何创建上下文,并如何使用上下文的呢?
// app.js export const ThemeContext = React.createContext(themes.light); export default class App extends React.Component { const value = {name: 'dengpeng'} render() { return ( <ThemeContext.Provider value={value}> <Container /> </ThemeContext.Provider> ) } } // container.js 使用Consumer import { ThemeContext } from 'app.js' class Container extends React.Component { render() { return ( <ThemeContext.Consumer> { value => ( <div>{value.name}</div> ) } </ThemeContext.Consumer> ) } } // container.js 使用Hooks import React, {useContext} from 'react'; import { ThemeContext } from 'app.js'; function Container:FC = () => { const value = useContext(ThemeContext); return ( <div>{value.name}</div> ) }
根据上面例子可以看出,使用Hooks 省略了ThemeContext.Consumer的包裹,并且也不用使用函数回调的方式,可以直接使用useContext获取context的数据。
提醒事项:
useState为什么返回的是一个数组呢,而不是一个{}呢? 首先,返回的是数组意味着这里采用的是数组解构,就等价于 等号左边的变量名 可以自定义。 如果是{}那么里面的变量肯定是固定的,只有通过别名才能保持不一样,所以展示效果不太好,比如
// 数组方式 const fruitArray = useState('apple'); // 等号作品可以随意取名 const fruit = fruitArray(0); const setFruit = fruitArray(1); // 所以数组解构 const [fruit1, setFruit1] = useState('apple'); const [fruit2, setFruit2] = useState('pear'); // {}方式,对象解构方式 const animalArray = useState('snake'); const animal = animalArray['animal']; const setAnimal = animalArray['setAnimal']; // 对象解构 const { animal: animal1, setAnimal: setAnimal1 } = useState('snake'); const { animal: animal2, setAnimal: setAnimal2 } = useState('snake'); // 从上面看来, 数组解构方式更加直观一点,而对象解构相对麻烦一点
在使用useEffect的时候,官网推荐启用 eslint-plugin-react-hooks 中的 exhaustive-deps 规则。此规则会在添加错误依赖时发出警告并给出修复建议。但是很多时候我们用到了不需要监听的依赖,启用后就会报错,应该如何解决呢
const [count, setCount] = useState(5) useEffect(() => { const query = location.search.query; document.title = '邓鹏博客' + count + query; // 在这里的依赖项正常情况下是[query, count],但是我们只需要监听到count变化才变化title,那怎么办呢 // 第一个办法是将query声明在effect外部 // 第二个办法是增加检测依赖项规则的忽略片段 // // eslint-disable-next-line react-hooks/exhaustive-deps (当然 官方是不推荐的哈) }, [count])
总之:react hooks更加接近函数编程,更加清晰的将React分成2个阶段,commit阶段和render阶段。后续会继续介绍react其他hooks。 博客首页 查看更多文章。 欢迎大家留言,给出意见!