目录
const myContext = useContext(MyContext);
Hooks
可以让React 函数组件具有状态,并提供类似 componentDidMount
和componentDidUpdate
等生命周期方法 。
函数组件专用
useState()
用来替代类中的state的状态,例如下面,相当于在state中初始化了一个count变量值为0,每次改变通过setCount(value),把value值赋给count(相当于setState({count:value})
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
// 声明一个叫 “count” 的 state 变量。 const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
useEffect(func,val)
func为一个函数。有返回函数时会在组件卸载和每次func函数执行前(除第一次,即用于清理上一次调用的效应)时被调用,没有则不调用。
当val不传时,组件初始化以及每次更新都会调用func函数。
当为空数组时,组件在初始化时调用func函数。
当val为数组时,组件在初始化时和每次数组中的任何一个变量发生变化时调用func函数。
注意比较变量发生变化时,如果是对象比较的是对象的引用,例如下面effect只会在初始化是打印一次,之后由于比较的是引用一直没有改变。
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState({a: 12});
useEffect(() => {
console.log('effect');
return () => {
console.log('clean')
}
}, [count])
function handleClick() {
count.a++;
setCount(count)
}
// 点击按钮时发现屏幕显示的值不发生变化,而且effect里面的函数也没有执行
//所以进行的是浅比较,这点类似于pureComponent
return (
<div>
<p>You clicked {count.a} times</p>
<button onClick={handleClick}>
Click me
</button>
</div>
);
}
useEffect中使用setInterval需要注意,例如下面传入count,实际上每次传入的是初始值0,不会把count实时的值传入。
有2种改法,1.第二个参数,数组改为[count],每一轮都会设置计时器,清除计时器。2.setCount改为setCount(preCount => preCount + 1);建议使用第二种。
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setCount(count + 1);
}, 1000);
// 定时器只加一次的原因在于虽然setInterval函数里面的函数每秒都会执行一次,
//但是count值始终是初始的0,因为这个函数绑定了第一轮render之后的count值,
return () => clearInterval(id);
}, []);
return <h1>{count}</h1>;
}
替代生命周期示例
https://blog.csdn.net/AIWWY/article/details/123338490
useContext
用于共享那些对于一个组件树而言是“全局”的数据(多层父子组件传递数据,不用一层一层传递数据)。 搭配React.createContext、Context.Provider、Context.Consumer等使用。
React.createContext
const MyContext = React.createContext(defaultValue);
创建一个 Context 对象。当 React 渲染一个订阅了(订阅相当使用useContext或Context.Consumer)这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider
中读取到当前的 context 值。
注意:只有当组件所处的树中没有匹配到 Provider 时,其 defaultValue
参数才会生效。此默认值有助于在不使用 Provider 包装组件的情况下对组件进行测试。将 undefined
传递给 Provider 的 value 时,消费组件的 defaultValue
不会生效。
Context.Provider
<MyContext.Provider value={/* 某个值 */}>
每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。 这里的MyContext是React.createContext函数返回的变量名。
Provider 接收一个 value
属性,传递给消费组件(useContext或Context.Consumer)。一个 Provider 可以和多个消费组件有对应关系。多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据。
当 Provider 的 value
值发生变化时,它内部的所有消费组件都会重新渲染。从 Provider 到其内部 consumer 组件(包括 .contextType 和 useContext)的传播不受制于 shouldComponentUpdate
函数(见生命周期方法),因此当 consumer 组件在其祖先组件跳过更新的情况下也能更新。 新旧值检测来确定变化,使用了与 Object.is 相同的算法
const myContext = useContext(MyContext);
相当于订阅Context.Provider中value值,此时可以通过 myContext访问value值。
注意myContext的值等于传递给函数的 value
值等价于组件树上方离这个 context 最近的 Provider 提供的 value
值。如果没有对应的 Provider,value
参数等同于传递给 createContext()
的 defaultValue
。
Context.Consumer
<MyContext.Consumer>
{value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>
和useContext相同,也相当于订阅了Context.Provider中的value值。
Class.contextType
MyClass.contextType = MyContext;
MyClass为类组件名,MyContext为由React.createContext()创建的Context 对象。此属性可以让你使用 this.context
来获取最近 Context 上的值(即在该类组件中可以通过this.context访问MyContext.Provider上的value值)。你可以在任何生命周期中访问到它,包括 render 函数中。
实例
const themes = {
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);
return (
<>
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
<ThemeContext.Consumer>
{value => <button style={{background:value.background,
color:value.foreground}}>I am styled by theme context too!</button>}
</ThemeContext.Consumer>
</>
);
}