REACT

REACT
Tomreact 简介
React 用于构建用户界面的 JavaScript 库,React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。
react特点
- 声明式设计:React采用声明范式,可以轻松描述应用。
- 高效:React通过对DOM的模拟,最大限度地减少与DOM的交互。
- 灵活:React可以与已知的库或框架很好地配合。
react不同于vue的mvvm,react只负责视图层view层
react 脚手架使用
- Node >= 8.10 和 npm >= 5.6
- 安装脚手架
npm install create-react-app -g - 查看脚手架版本
create-react-app --version - 创建项目
create-react-app xxxx- 进入项目目录
cd xxxx - 启动项目
npm start - 编译打包
npm run build
- 进入项目目录
第一个react应用
1 | <div id="root"></div> |
JSX
JSX是一种JavaScript的语法扩展,运用于React架构中,其格式比较像是模版语言,但事实上完全是在JavaScript内部实现的。React使用JSX来描述用户界面。使用JSX语法可以让我们在 js编写类似HTML的标签
JSX语法编写的代码并不能直接在浏览器中运行需要经过 babel 进行编译才会被浏览器识别。
1 | // JSX |
- jsx标签必须包含在根标签下,否则会报语法错误。
JSX 注释
在JSX中可以插入注释语句,语法{/* */}
1 | let template = <div> |
JSX 插入js表达式
使用 花括号 {}可以在JSX插入JS表达式
1 | let num =199; |
JSX 变量类型
JSX 表达式中可以插入任意类型的变量。
- JSX插入以下三种类型的值并不能直接渲染到DOM
BoolanNullundefined
- 数组:插入的如果是数组类型那么,会自动展开所有数组成员。
JSX 表达式直接使用插入的数据是安全的
React DOM 在渲染之前默认会 过滤 所有传入的值会将所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(跨站脚本) 攻击。
1 | <!-- 接收用户输入 --> |
JSX 属性
JSX 语法上更接近 JavaScript 而不是 HTML,所以 React DOM 使用 camelCase(小驼峰命名)来定义属性的名称,而不使用 HTML 属性名称的命名约定。
例如,JSX 里的 class 变成了 className,而 tabindex 则变为 tabIndex。
1 | let template = <div> |
使用花括号 {} 为属性插入一个JS表达式
1 | let tValue = '这是一个标题' |
style 属性
在JSX中使用style来设置样式时,style的值必须是一个对象,各个样式属性作为key(驼峰命名),样式值为value
1 | var myStyle = {color:"#ff0000",fontSize:40}; |
JSX 事件
JSX 支持所有的 HTML 元素的事件,但是有一点语法上的不同。
- React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
- 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
1 | function fun1(ev) { |
在 React 中另一个不同点是你不能通过返回
false的方式阻止默认行为。你必须显式的使用preventDefault()。
事件回调函数中传递数据
JSX 可以通过箭头函数的方式向事件回调函数中传递数据
1 | function fun1(...args) { |
通过bind函数向传递数据
1 | function fun1(args) { |
更新已渲染的元素
React元素都是不可变的。当元素被创建之后,你是无法改变其内容或属性的。一个元素就像电影的单帧:它代表了某个特定时刻的 UI。
如果要更新已经渲染界面可以通过重新通过render方法渲染。React DOM 会将元素和它的子元素与它们之前的状态进行比较,React 只会更新必要的部分
1 | let msg='msg' |
列表渲染
for循环
1
2
3
4
5
6
7
8
9
10let colors = ['red','blue','green','yellow']
let colorsJSX = []
// 将数组中内容展开到JSX表达式中
for (let i = 0; i < colors.length; i++) {
colorsJSX.push( <li key={i}>{colors[i]}</li> )
}
let template = <div>
<ul>{colorsJSX}</ul>
</div>map()1
2
3
4
5
6
7let colors = ['red','blue','green','yellow']
let colorsJSX = colors.map( (item,index) =>
<li key={index}>{item}</li> )
let template = <div>
<ul>{colorsJSX}</ul>
</div>列表中元素需要设置 key 属性,数组元素中使用的 key 在其兄弟节点之间应该是独一无二的。
JSX中嵌入
map()。JSX 允许在花括号中嵌入任何表达式1
2
3
4
5
6
7
8let colors = ['red','blue','green','yellow']
let template = <div><ul>
{
colors.map( (item,index) =>
<li key={index}>{item}</li> )
}
</ul></div>
组件
组件就是将UI 拆分为独立可复用的代码片段。
注意: 组件名称必须以大写字母开头。
组件创建三种方式:
函数式组件
1
2
3
4
5
6
7
8function Home(props) {
return <div className='home'>
<h2>home</h2>
<p>{props.msg}</p>
</div>
}
ReactDOM.render(<Home msg='123'/>, document.getElementById('root'));函数式组件在与用户交互时不方便,无状态,适用于静态展示
简单,性能好,不需要实例化,无生命周期。React.ComponentES6 CLASS语法定义组件1
2
3
4
5
6
7
8
9
10
11
12
13class Home extends React.Component{
constructor(props){
super(props)
}
render(){
return <div>
<h2>home</h2>
<p>{this.props.msg}</p>
</div>
}
}
ReactDOM.render(<Home msg='hello'/>, document.getElementById('root'));constructor构造函数是可选的。React.createClassES5语法定义组件1
2
3
4
5
6
7
8
9const Home = React.createClass({
render:function(){
return <div>
hello,class component,{this.props.msg}
</div>
}
});
ReactDOM.render(<Home msg='hello'/>, document.getElementById('root'));React.createClass需要在15.5之前版本才能使用,新版本不再支持。
props
通过props可以向组件内部传递数据
props是只读的,任何时候都不要修改props中的数据
props默认值
React.createClass1
2
3
4
5
6
7
8
9
10
11
12const Home = React.createClass({
getDefaultProps: function() {
return {
msg:'默认值'
};
},
render:function(){
return <div>
hello,class component,{this.props.msg}
</div>
}
});React.Component1
2
3
4
5
6
7
8
9
10
11class Home extends React.Component{
render(){
return <div>
<h2>home</h2>
<p>{this.props.msg}</p>
</div>
}
}
Home.defaultProps ={
msg:"Hello,World"
}函数式
1
2
3
4
5
6
7
8
9function Home(props) {
return <div className='home'>
<h2>home</h2>
<p>{props.msg}</p>
</div>
}
Home.defaultProps ={
msg:"Hello,JSX"
}
props类型验证
自 React v15.5 起,
React.PropTypes已移入另一个包中。请使用 prop-types 库 代替。
React.createClass1
2
3
4
5
6
7
8
9
10
11const Home = React.createClass({
// 类型验证
propTypes: {
msg:React.PropTypes.string,
},
render:function(){
return <div>
hello,class component,{this.props.msg}
</div>
}
});函数式组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14<script crossorigin src="https://unpkg.com/prop-types@15.7.2/prop-types.js"></script>
...
function Home(props) {
return <div className='home'>
<h2>home</h2>
<p>{props.msg}</p>
</div>
}
//设置组件的属性类型验证
Home.propTypes ={
msg:PropTypes.string,
}
ReactDOM.render(<Home msg={123}/>, document.getElementById('root'));React.Component1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<script crossorigin src="https://unpkg.com/prop-types@15.7.2/prop-types.js"></script>
...
class Home extends React.Component{
render(){
return <div>
<h2>home</h2>
<p>{this.props.msg}</p>
</div>
}
}
Home.propTypes ={
msg:PropTypes.number,
}
ReactDOM.render(<Home msg='998'/>, document.getElementById('root'));
PropTypes以下提供了使用不同验证器的例子:
1 | import PropTypes from 'prop-types'; |
组件中事件
1 | class Home extends React.Component{ |
组件中事件回调函数时中使用this,this的值为undefined。
使用
bind函数修正this指向1
2
3
4
5
6
7
8
9
10
11class Home extends React.Component{
btnClick(ev){
console.log(this.props)
}
render(){
return <div>
{/* 使用bind修正this指向 */}
<button onClick={this.btnClick.bind(this)}>按钮</button>
</div>
}
}也可以在构造函数中修改,修正后可以直接在元素中调用该方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Home extends React.Component{
constructor(props){
super()
// 修正this指向
this.btnClick = this.btnClick.bind(this)
}
btnClick(ev){
console.log(this)
}
render(){
return <div>
<button onClick={this.btnClick}>按钮</button>
</div>
}
}使用箭头函数
1
2
3
4
5
6
7
8
9
10
11class Home extends React.Component{
btnClick(ev){
console.log(this)
console.log(ev)
}
render(){
return <div>
<button onClick={ev=>this.btnClick(ev)}>按钮</button>
</div>
}
}
state
更新已经渲染的元素可以使用 state
this.forceUpdate()强制刷新视图
- 在构造函数中初始化
state数据 - 更新
state中数据调用setState()
ES6 class语法创建组件 设置 state
1 | class Home extends React.Component{ |
state更新数据是异步的如果想要获取更新后的值可以监听setState中的回调函数来获取新值
1 | this.setState(function(newState) { |
createClass组件中的state
为createClass组件添加state可以使用 getInitialState
1 | const Home = React.createClass({ |
组件生命周期
函数式组件没有状态,没有生命周期。类组件才有生命周期
生命周期方法
componentWillMount()准备挂载componentDidMount()挂载完成componentWillReceiveProps()接收到父组件传递的props数据shouldComponentUpdate(nextProps,nextState)组件可能要更新componentWillUpdate(nextProps, nextState)准备更新componentDidUpdate(prevProps,prevState)更新完成componentWillUnmount()组件卸载
两个可以触发生命周期的方法
forceUpdate()强制重新渲染界面ReactDOM.unmountComponentAtNode(document.querySelector('#root'))卸载组件
以上两个方法不推荐使用。
性能优化
shouldComponentUpdate(nextProps,nextState)
此方法仅作为性能优化的方式而存在。不要企图依靠此方法来“阻止”渲染,因为这可能会产生 bug。你应该考虑使用内置的 PureComponent 组件,而不是手动编写 shouldComponentUpdate()。PureComponent 会对 props 和 state 进行浅层比较,并减少了跳过必要更新的可能性。
如果你一定要手动编写此函数,可以将 this.props 与 nextProps 以及 this.state 与nextState 进行比较,并返回 false 以告知 React 可以跳过更新。请注意,返回 false 并不会阻止子组件在 state 更改时重新渲染。
我们不建议在 shouldComponentUpdate() 中进行深层比较或使用 JSON.stringify()。这样非常影响效率,且会损害性能。
受控组件
在 HTML 中,表单元素(如<input>、 <textarea>和 <select>)之类的表单元素通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态 (mutable state) 通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新。
一个受控组件中,表单数据是由 React 组件来管理。
<input />输入框1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Home extends React.Component{
constructor(props){
super()
this.state = {
value1 : ''
}
}
render(){
return <div>
<input type="text" value={this.state.value1}
onChange={ev=>this.setState({value1:ev.target.value})}/>
<h2>{this.state.value1}</h2>
</div>
}
}单选框
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Home extends React.Component{
constructor(props){
super()
this.state = {
isRemeber : false
}
}
render(){
return <div>
<input type="checkbox" checked={this.state.isRemeber}
onChange={ev=>this.setState({isRemeber: !this.state.isRemeber})}/>
<h2>{this.state.isRemeber?"true":"false"}</h2>
</div>
}
}复选框
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45class Home extends React.Component{
constructor(props){
super()
this.state = {
colors:['red','blue'],
}
this.hanldInput = this.hanldInput.bind(this)
}
// 复选框改变事件
hanldInput(ev){
//添加
if(ev.target.checked){
this.setState({
colors:[
...this.state.colors,
ev.target.value
]
})
}else{ //删除
//获取到要删除的下标
let i = this.state.colors.indexOf(ev.target.value)
this.setState({
colors:[
...this.state.colors.slice(0,i),
...this.state.colors.slice(i+1)
]
})
}
}
render(){
return <div>
<input type='checkbox' checked={this.state.colors.includes('red')}
onChange={this.hanldInput}
value='red' />red
<input type='checkbox' checked={this.state.colors.includes('blue')}
onChange={this.hanldInput}
value='blue' />blue
<input type='checkbox' checked={this.state.colors.includes('green')}
onChange={this.hanldInput}
value='green' />green
<div>颜色:{this.state.colors}</div>
</div>
}
}select1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23class Home extends React.Component{
constructor(props){
super(props)
this.state = {value: 'coconut'};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
console.log(event.target.value)
}
render(){
return <div>
<h2>home</h2>
选择你喜欢的风味:
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">葡萄柚</option>
<option value="lime">酸橙</option>
<option value="coconut">椰子</option>
<option value="mango">芒果</option>
</select>
</div>
}
}
有时使用受控组件会很麻烦,因为需要为数据变化的每种方式都编写事件处理函数,并通过一个 React 组件传递所有的输入 state。当你将之前的代码库转换为 React 或将 React 应用程序与非 React 库集成时,这可能会令人厌烦。在这些情况下,你可能希望使用非受控组件, 这是实现输入表单的另一种方式。
refs
refs属性暴露组件的DOM元素
何时使用 Refs
下面是几个适合使用 refs的情况:
- 管理焦点,文本选择或媒体播放。
- 触发强制动画。
- 集成第三方 DOM 库。
避免使用
refs来做任何可以通过声明式实现来完成的事情。
refs获取有两种方式
React 16.3 版本之前使用回调函数方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Home extends React.Component{
constructor(props){
super()
// 接收DOM对象
this.input1 = null
}
render(){
return <div>
{/*回调函数方式获取ref*/}
<input type="text" ref={el=>{this.input1 = el;}}/>
</div>
}
componentDidMount() {
console.log(this.input1)
}
}React 16.3 版本使用的 React.createRef()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Home extends React.Component{
constructor(props){
super()
// 16.3版本使用
this.input1 = React.createRef()
}
render(){
return <div>
<input type="text" ref={this.input1} />
</div>
}
componentDidMount() {
console.log(this.input1)
}
}
非受控组件
非受控组件,表单数据将交由 DOM 节点来处理。非受控组件可以 使用 ref 来从 DOM 节点中获取表单数据。
1 | class Home extends React.Component { |
内容分发
内容分发是指通过组件内容或组件属性向组件传递数据。
默认内容分发
props.children对组件内已有内容进行保留
1 | class Home extends React.Component { |
指定内容分发
1 | class Home extends React.Component { |
高阶组件
高阶组件是参数为组件,返回值为新组件的函数。
1 | //高阶函数 |
路由
下载路由文件
- 只下载
react-router-dom,其它不用下载 npm install --save react-router-dom- cdn
<script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script>
ReactRouterDOM类
Route: (抽象类) 路由对象,匹配浏览器地址栏url,所有路由记录都必须嵌套在该组件内。BrowserRouter: (Router的实现类)按H5 history 模式匹配urlHashRouter:(Router的实现类)按 hash 模式匹配urlStaticRouter:(Router的实现类)MemoryRouter:(Router的实现类)Redirect: 重定向,必须配合<Switch>一起使用
react不像vue路由规则匹配成功后就不往后面匹配了,react会将所有规则全部匹配。
react 路由规则配合上<Switch>组件使用就会匹配上第一个后就不再向后匹配,如果没有匹配上就继续匹配。
Link声明性,可访问的导航。NavLink:与Link不同点在于会动态的添加一个active类名
NavLink组件中也要加上exact否则匹配时可能会出现都出现active类名的现象。
- 也可以指定自已的类名
1 | <NavLink to='/goods/food' activeClassName='my-active' exact>食物</NavLink> |
路由使用
1 | // 获取路由对象 |
路由重定向
1 | <Redirect push to='/' /> |
push为true时,重定向会将新条目推送到历史记录而不是替换当前条目。
路由规则匹配模式
exact精确模式
1 | <Route exact path="/one" component={About} /> |
path |
location.pathname |
exact |
匹配 |
|---|---|---|---|
/one |
/one/two |
true |
no |
/one |
/one/two |
false |
yes |
strict严格模式
1 | <Route strict path="/one/" component={About} /> |
path |
location.pathname |
匹配 |
|---|---|---|
/one/ |
/one |
no |
/one/ |
/one/ |
yes |
/one/ |
/one/two |
yes |
1 | <Route exact strict path="/one" component={About} /> |
path |
location.pathname |
匹配 |
|---|---|---|
/one |
/one |
yes |
/one |
/one/ |
no |
/one |
/one/two |
no |
strict会强制检查路径尾部是否有斜杠。
嵌套路由
- 嵌套路由,首先会匹配到主路由规则然后再匹配子路由。
- 主路由匹配规则中不能添加
exact,如果添加的话子路由将匹配不到。
1 | class Home extends React.Component{ |
动态路由
1 | <Route path="/users/:id" component={User} /> |
props.match.params接收动态路由传递的参数
1 | class Home extends React.Component{ |
路由编程式导航
- 不是路由组件,但想使用路由组件中的对象方法,那么可以使用
withRouter高阶组件进行封装。
1 | class Home extends React.Component{ |
路由懒加载
React.lazy(), 加载异步组件1
const Set = React.lazy(() => import("../views/set"))
使用
React.lazy的动态引入特性需要 JS 环境支持Promise。在 IE11 及以下版本的浏览器中需要通过引入polyfill来使用该特性。React.Suspense,suspence是用来包裹异步组件,添加loading效果等1
2
3
4
5<React.Suspense fallback={<div>loading....</div>}>
...
<Route path='/set' component={Set}/>
...
</React.Suspense>React.lazy使用import来懒加载组件,import在webpack中最终会调用requireEnsure方法,动态插入script来请求js文件,类似jsonp的形式。
redux
- 状态模式管理库(实现react中数据共享)
- 官方的是:flux
- redux 是第三方的
- redux英文
- redux中文
- cdn
https://unpkg.com/redux@4.0.1/dist/redux.js
redux核心概念
store存储数据Reducer普通函数(不能有异步操作),接收上一次的state以及用户的行为action产生一个新的stateAction普通对象,记录用户行为以及传输的参数
redux 使用
1 | //1. 创建 Reducer |
Reducers 合并
- 调用
Redux.combineReducers()将多个合并为一个
1 | let rootReducers = Redux.combineReducers({ |
- 使用合并过的
Reducers需要加上合并时的Reducers名称。
1 | store.getState().taskList |
合并后
Reducers后 相关type的Reducers都会被触发。
react 与 redux 结合使用
- react-redux文档
npm i react-redux- cdn
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.0.3/react-redux.js"></script> - react-redux 将 react 与 redux 结合在一起
要使用
react-redux需要先引入redux库
react-redux 核心
Provider组件,用户于挂载redux对象,Provider所包含的所有组件都可以获取到store1
2
3<Provider store={}>
...在这里写组件,必须要有根元素
</Provider>普通组件通过
connect连接可以使用store中数据1
const NewMyComponent = ReactRedux.connect(mapStateToProps,mapDispatchToProps)(MyComponent)
react-redux 使用
1 | // 创建 Reducer |
hook
Hook 是 React 16.8 的新增特性。它可以让你在不编写
class的情况下使⽤state以及其他的 React 特性。
在我们继续之前,请记住 Hook 是
- 完全可选的。 你⽆需重写任何已有代码就可以在⼀些组件中尝试 Hook。但是如果你不想,你不必现在就去学习或使⽤Hook。
- 100% 向后兼容的。 Hook 不包含任何破坏性改动。
- 现在可⽤。 Hook 已发布于 v16.8.0。
- 没有计划从 React 中移除 class。
- Hook 不会影响你对 React 概念的理解。 恰恰相反,Hook 为已知的 React 概念提供了更直接的 API:
props,state,context,refs以及⽣命周期。Hook 还提供了⼀种更强⼤的⽅式来组合他们。
React Hooks解决了什么问题?
函数组件不能使⽤
state,⼀般只⽤于⼀些简单⽆交互的组件,⽤作信息展示,即我们上⾯说的傻⽠组件使⽤,如果需要交互更改状态等复杂逻辑时就需要使⽤class组件了React Hooks让我们更好的拥抱函数式编程,让函数式组件也能使⽤state功能,因为函数式组件⽐class组件更简洁好⽤,
因为React Hooks的出现,相信未来我们会更多的使⽤函数式组件副作⽤问题
- 我们⼀般称数据获取、订阅、定时执⾏任务、⼿动修改ReactDOM这些⾏为都可以称为副作⽤
- 由于React Hooks的出现,我们可以使⽤
useEffect来处理组件副作⽤问题,所以我们的函数式组件也能进⾏副作⽤逻辑的处理了
有状态的逻辑重⽤组件
复杂的状态管理
- 之前我们使⽤
redux、dva、mobx第三⽅状态管理器来进⾏复杂的状态管理 - 现在我们可以使⽤
useReducer、useContext配合使⽤实现复杂状态管理,不⽤再依赖第三⽅
- 之前我们使⽤
开发效率和质量问题
- 函数式组件⽐class组件简洁,开发的体验更好,效率更⾼同时应⽤的性能也更好
hook使用
HOOK 使用规则
- 只在最顶,不要在循环,条件或嵌套函数中调用 Hook。确保总是在你的 React 函数的最顶层调用他们。遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。层使用 Hook
- 只在 React 函数中调用 Hook,不要在普通的 JavaScript 函数中调用 Hook。
React.useState()
组件状态管理钩⼦
能使函数组件能够使⽤state
useState 的使用
1 | const [state,setState] = React.useState(initState) |
解构时一定要注意顺序
state是要设置的状态setState是更新state的⽅法,只是⼀个⽅法名,可以随意更改initState是初始的state,可以是随意的数据类型。也可以是回调函数,如果函数时必须返回数据##。
1 | const { useState } = React |
声明多个 state
hook 允许使用多个 state 变量,需要给不同的 state 变量取不同的名称
1 | const [age, setAge] = useState(42); |
React.Effect
Effect Hook 可以让你在函数组件中执行副作用操作
数据获取、订阅、定时执⾏任务、⼿动修改ReactDOM这些⾏为都可以称为副作⽤。
⽽useEffect就是为了处理这些副作⽤⽽⽣的useEffectHook 也可以看做componentDidMount,componentDidUpdate和componentWillUnmount这三个函数的组合在
useEffect中可以访问 state 变量(或其他 props)
Effect Hook 语法
1 | React.useEffect(callback,array) |
callback回调函数,作⽤是处理副作⽤逻辑。callback中返回值是可选的。callback返回函数的话那么该函数会在`componentWillUnmount` 之后调用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15const { useState, useEffect } = React
function Home(props) {
useEffect(()=>{
//处理这些副作⽤ 的代码
...
// componentWillUnmount` 之后调用
return ()=>{
console.log('end')
}
})
return (<div>
<h2>home</h2>
</div>)
}
array(可选参数):数组,⽤于控制useEffect 回调函数的执⾏,有三种情况- 空数组,则只会执⾏⼀次(即初次渲染render)。相当于
componentDidMount - ⾮空数组,useEffect会在数组发⽣改变后执⾏。相当于
componentDidUpdate - 不填array这个数组,useEffect每次渲染都会执⾏
- 空数组,则只会执⾏⼀次(即初次渲染render)。相当于
React.useContext
更⽅便的实现全局数据共享的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23const { useState, useEffect,useContext } = React
const c1=React.createContext({age:'18',name:'小明'})
const c2=React.createContext({age:'88',name:'小明1'})
function Home(props) {
//使⽤useContext
const ctx =useContext(c1)
return (<div>
<h2>home</h2>
<h3>{ctx.age}</h3>
<h3>{ctx.name}</h3>
</div>)
}
function About(props) {
//使⽤useContext
const ctx =useContext(c2)
return (<div>
<h2>about</h2>
<h3>{ctx.age}</h3>
<h3>{ctx.name}</h3>
</div>)
}
React.useReducer
是
useState的⼀个增强体,可以⽤于处理复杂的状态管理useReducer可以完全替代useState,只是我们简单的状态管理⽤useState⽐较易⽤,useReducer的设计灵感源⾃于redux的reducerReact.useReducer语法:1
const [state, dispatch] = useReducer(reducer, initialArg, init);
reducer是⼀个函数,根据action状态处理并更新stateinitState是初始化的stateinitAction是useReducer初次执⾏时被处理的action ,(可选的)。- 返回:
state状态值dispatch是更新state的⽅法,他接受action作为参数
1 | const { useReducer } = React |
自定义HOOK
- 自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook
- 通过自定义 Hook,可以将组件逻辑提取到可重用的函数中
1 | const { useEffect } = React |











