React 导学课2
useContext()
上下文hook,接受一个上下文对象,并返回当前上下文
创建上下文:
import { createContext } from 'react';
const MyContext = createContext('default');
//这里的值是最终的保底值,根据业务类型放个默认值
当前上下文的值由树中调用组件上方的value最近的 prop确定
<MyContext.Provider value = {???}>
{/* 这里的value是想赋给上下文Provider标签域内的value */}
<Component1 />
<Component2 />
</MyContext.Provider>
当最近的MyContext.Provider组件更新时,此hook将触发更新并重新渲染,并将最近的上下文value传递给MyContex提供程序,重新渲染的话仍然会从组件本身开始使用useContext。
useContext里同时可以传入函数:
const [textContext, setTextContext] = useState('123')
return (
<MyContext.Provider value={[textContext, setTextContext]}>
{/* 此时Parent组件便可以使用useContext接收到两个参数:初始值('123')和函数setTextContext */}
<Parent />
</MyContext.Provider>
)
useContext()总是在调用它的组件上方寻找最近的提供者。它向上搜索并且不考虑您从中调用的组件中的提供程序useContext()。
所以要小心你的provider是否嵌套,看一个demo试试
useRef()
const ref = useRef(initialValue)
useRef在组件的顶层调用以声明一个或多个refs。
useRef返回一个具有单个属性的ref 对象,该属性最初设置为您提供的初始值。current
import { useRef } from 'react';
function Stopwatch() {
const intervalRef = useRef(0);
// ...
通过使用 ref,您可以确保:
- 您可以在多次渲染之间存储信息。(与在每次渲染时重置的常规变量不同。)
- 更改它不会触发重新渲染。(与触发重新渲染的状态变量不同。)
- 该信息对于组件内所有子组件都是可读的。(与外部的变量不同,它们是共享的。)
更改 ref 不会触发重新渲染,因此 ref 不适合存储显示类的信息。
import { useRef } from 'react';
export default function Counter() {
let ref = useRef(0);
function handleClick() {
ref.current = ref.current + 1;
alert('You clicked ' + ref.current + ' times!');
}
return (
<button onClick={handleClick}>
Click me!
</button>
);
}
使用 ref 操作 DOM
使用 ref 来操作DOM尤其常见。React 对此有内置支持。
首先,声明一个初始值为的ref 对象:null
然后将您的 ref 对象作为ref属性传递给您要操作的 DOM 节点的 JSX:
import { useRef } from 'react';
function MyComponent() {
const inputRef = useRef(null);
// ...
return <input ref={inputRef} />;
}
function Form() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
}
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>
Focus the input
</button>
</>
);
}
正因为对DOM的操作频繁,我们更希望在一次使用后继续保存ref对象。所以我建议初始化以null初始,然后用if对ref做判断之后再,创建对象或赋值
function Video() {
const playerRef = useRef(null);
//而不是一开始就创建useRef(new VideoPlayer())
function getPlayer() {
if (playerRef.current !== null) {
return playerRef.current;
}
const player = new VideoPlayer();
playerRef.current = player;
return player;
}
组件内传递Ref
import { forwardRef } from 'react';
const MyInput = forwardRef(({ value, onChange }, ref) => {
return (
<input
value={value}
onChange={onChange}
ref={ref}
/>
);
};
//父组件中:
//const inputRef = useRef(null);
// return <MyInput ref={inputRef} />
export default MyInput;