一、函数式组件创建
function HelloComponent(props, /* context */) {
return <div>Hello {props.name}</div>
}
ReactDOM.render(<HelloComponent name="Sebastian" />,document.getElementById("mountNode"))
这里我们可以知道该组件中并没有自己的状态,但实际开发中往往需要内部的状态实现一系列的交互和展示功能.所以我们用class创建组件更多一点.但是,纯函数的组件式创建更符合react的思想,于是为了解决状态问题,完善的函数式组件创建模式出现:react-hook
首先需要明确的一点是,hook中没有this指针,所以相关的api都需要改变才.
二、常用HOOK API
结合class式组件进行对比
1.组件申明
class:
export default class Text extends React.Component {}
Hook
const Text = {}
export default Text
2.state
(1)初始化
class
constructor(props) {
super(props);
this.state = {
name: '小明',
age:1
};
}
Hook
const [name, setName] = useState(0);
const [age, setAge] = useState(1);
//name:变量名 初始值是useState()里面额值,相当于name=0,同时又申明了一个函数setName并使其具有监听name变化然后更新视图的功能
//setName:传一个新的name值,并更新至视图层.可以是一个具有返回值的函数
(2)获取state值
class
this.state.name
this.state.age
Hook
const [name, setName] = useState('小明');
const [age, setAge] = useState(1);
useState('小明')//获取name,自动忽略参数
useState(1)//获取age,自动忽略参数
(3)修改state值
class
this.setState({age:18})
//实际上是修改的this.state的里面的元素
Hook
setAge(18)
//传入一个新的age值,自动渲染至视图层.不同于setState(),只能一次设置一个特定变量.
3.props
用法差不多,只不过hook不用初始化,直接将参数拿来用.
4.生命周期
class
componentWillMount //在渲染前调用,在客户端也在服务端。
componentDidMount : //在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
componentWillReceiveProps //在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
shouldComponentUpdate //返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
可以在你确认不需要更新组件时使用。
componentWillUpdate//在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
componentDidUpdate //在组件完成更新后立即调用。在初始化时不会被调用。
componentWillUnmount//在组件从 DOM 中移除之前立刻被调用。
Hook
生命周期的实质就是回调函数,只不过用不同的生命周期表示不同阶段的回调函数.目前Hook只有一个回调函数useEffect(),但是在多个阶段触发
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); useEffect(() => { // 如果你熟悉 React class 的生命周期函数,你可以把useEffect
Hook 看做componentDidMount
,componentDidUpdate
和componentWillUnmount
这三个函数的组合。 document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
另外,useEffect()还可以手动设置依赖项,它可以接收两个参数,第一个是函数,第二个是依赖项(数组),第二个参数给的话就依据依赖项时候更改决定是否调用,不给就类似上面的用法.
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
},[count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
5.comtext
具体的需求就是组件之间的的状态共享,比如兄弟之间、爷孙之间,跨组件的状态共享.解决了参数需要逐层往下传递的麻烦.
class
// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的 theme 创建一个 context(“light”为默认值)。
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
// 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
// 无论多深,任何组件都能读取这个值。
// 在这个例子中,我们将 “dark” 作为当前的值传递下去。
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
// 中间的组件再也不必指明往下传递 theme 了。
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
class ThemedButton extends React.Component {
// 指定 contextType 读取当前的 theme context。
// React 会往上找到最近的 theme Provider,然后使用它的值。
// 在这个例子中,当前的 theme 值为 “dark”。
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}
Hook
const themes = {
light: {
foreground: "#000000",
background: "#eeeeee"
},
dark: {
foreground: "#ffffff",
background: "#222222"
}
};
const ThemeContext = React.createContext(themes.light);
function App() {
return (
<ThemeContext.Provider value={themes.dark}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext); //由于没有了this,所以我们需要用这个api来获取context,然后使用.其他的用法一样
return (
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
);
}
6.ref
这里主要针对,ref绑定字符串这种形式的使用.回调函数的用法是一样的,其根本原因还是Hook并没有"this.refs"这种获取ref的方式
class
<input ref="input" />
let inputEl = this.refs.input;//这里拿到对应的ref,然后处理相关逻辑
Hook
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
7.reducer
class
this.props.dispatch({type:'/api'})
Hook
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
待补充
来源:oschina
链接:https://my.oschina.net/u/4308120/blog/3321337