一、React表单控制
表单控制是React应用中常见的需求,React Hooks提供了两种方式来实现:受控组件和非受控组件。
1.1 受控组件
受控组件是将表单输入的值保存在组件的状态中。这样,表单数据就完全由React控制。
import React, { useState } from 'react';
function ControlledInput() {
const [value, setValue] = useState('');
const handleChange = (e) => {
setValue(e.target.value);
};
return <input type="text" value={value} onChange={handleChange} />;
}
1.2 非受控组件
非受控组件不使用React的状态来控制输入值,而是通过直接操作DOM来获取输入值。
import React, { useRef } from 'react';
function UncontrolledInput() {
const inputRef = useRef(null);
const handleChange = () => {
console.log(inputRef.current.value);
};
return <input type="text" ref={inputRef} onChange={handleChange} />;
}
二、React组件通信
组件通信是React应用中另一个重要的概念,它允许不同组件之间进行数据交换。
2.1 父子通信
父子组件之间的通信可以通过props实现。
function ParentComponent() {
const name = 'Parent Name';
return <ChildComponent name={name} />;
}
function ChildComponent(props) {
return <div>{props.name}</div>;
}
2.2 子传父通信
子组件可以通过回调函数将数据传递给父组件。
function ParentComponent() {
const getMsg = (msg) => console.log(msg);
return <ChildComponent onGetMsg={getMsg} />;
}
function ChildComponent({ onGetMsg }) {
const handleClick = () => {
onGetMsg('this is son msg');
};
return <button onClick={handleClick}>Send Message</button>;
}
2.3 兄弟组件通信
兄弟组件通信通常通过提升状态到它们共同的父组件来实现。
function ParentComponent() {
const [name, setName] = useState('');
const handleAName = (name) => {
setName(name);
};
return (
<>
<AComponent onGetAName={handleAName} />
<BComponent name={name} />
</>
);
}
function AComponent({ onGetAName }) {
const handleClick = () => {
onGetAName('A Component Name');
};
return <button onClick={handleClick}>Send A Name</button>;
}
function BComponent({ name }) {
return <div>B Component Name: {name}</div>;
}
2.4 跨层组件通信
跨层组件通信可以通过React的Context API实现。
import React, { createContext, useContext, useState } from 'react';
const MsgContext = createContext();
function DeepChildComponent() {
const msg = useContext(MsgContext);
return <div>{msg}</div>;
}
function IntermediateComponent() {
return <DeepChildComponent />;
}
function ParentComponent() {
const msg = 'Message from Parent';
return (
<MsgContext.Provider value={msg}>
<IntermediateComponent />
</MsgContext.Provider>
);
}
三、React副作用管理:useEffect
useEffect
是React Hooks中用于处理副作用的函数,它可以在组件渲染后执行操作。
3.1 基本使用
import React, { useEffect, useState } from 'react';
function ComponentWithEffect() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Component did mount and update');
}, []); // 空依赖数组表示只在挂载时执行
return (
<div>
Count: {count}
</div>
);
}
3.2 清除副作用
useEffect
可以返回一个清除副作用的函数,通常用于定时器或订阅的清理。
function ComponentWithCleanup() {
useEffect(() => {
const timer = setInterval(() => {
console.log('Timer tick');
}, 1000);
// 清除副作用
return () => clearInterval(timer);
}, []); // 空依赖数组
return <div>Component with cleanup</div>;
}
四、自定义Hook实现
自定义Hooks允许你封装可复用的逻辑。
4.1 创建自定义Hook
import { useState, useCallback } from 'react';
function useToggle(defaultValue) {
const [value, setValue] = useState(defaultValue);
const toggle = useCallback(() => {
setValue(prevState => !prevState);
}, []);
return [value, toggle];
}
4.2 使用自定义Hook
function App() {
const [isOn, toggleOn] = useToggle(true);
return (
<div>
{isOn ? 'Toggle is ON' : 'Toggle is OFF'}
<button onClick={toggleOn}>Toggle</button>
</div>
);
}
4.3 React Hooks使用规则
- 只能在函数组件中使用:Hooks让你在不编写类的情况下使用state和其他React特性。
- 只能在顶层使用:不要在循环、条件判断或嵌套函数中调用Hooks。
结语
通过本文的探索,我们了解到React Hooks提供了一种强大且灵活的方式来构建组件。无论是表单控制、组件通信,还是副作用管理,Hooks都提供了简洁的解决方案。自定义Hooks的引入更是让我们能够复用状态逻辑,编写更干净、更可维护的代码。掌握这些概念和技巧,将极大地提升你的React开发能力。