react

react 组件渲染的触发条件

  1. 状态变化
    • 当使用 useStateuseReducer 等 Hook 修改组件的状态时,React 将重新渲染该组件。
    • 例如,调用 setState 函数更新状态变量会触发组件的重新渲染。
  2. 属性变化
    • 当父组件传递给子组件的属性(props)发生变化时,子组件会重新渲染。
    • 例如,如果父组件的状态更新导致传给子组件的属性值变化,子组件会根据新的属性重新渲染。
  3. 强制更新
    • 使用 forceUpdate 方法(通常不推荐使用)可以强制组件重新渲染,即使状态和属性没有变化。

基本语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 单条消息记录组件
interface RoomEntryProps {}
function RoomEntry (props: RoomEntryProps) {
return (); //在这里编写组件内部结构
}

// 需要暴露给App.tsx的页面
export default function ChatRoom() {
return (
<></>//在这里编写页面结构
);
}

//在App.tsx中引入该页面
import ChatRoom from './pages/ChatRoom/ChatRoom'

function App () {
return (
<>
<ChatRoom />
</>
)
}

路由

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
$ yarn add react-router-dom

//main.tsx
import {useNavigate, useLocation} from 'react-router-dom'
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
<HashRouter>
<App />
</HashRouter>
</React.StrictMode>
);

//App.tsx
export default function App() {


return (
<>
<Router>
<Routes>
<Route path="/chatroom" element={<Chatroom />} />
<Route path="/setname" element={<Setname />} />
<Route path="/" element={<Setname />} />
</Routes>
</Router>
{/* <Sidebar /> */}

</>
)
}


//components.tsx
const navigate = useNavigate(); //创建Navigate对象
const handleClick () => {
navigate('/home', { state: { name: currentUser.name } });
};

//前进、后退
const handleClick () => {
navigate(-1); //后退
navigate(1); //前进
};
//作为组件
const App () => {
return <Navigate to='/home' state={state} />;
};

//home.tsx
const location=useLocation();
const [nickname] = useState<string>(location.state.name);
//跳转至另一页面并使用刚才页面的值时可以使用useNavigate() 进行传值,并使用useLocation() 接受值


//另一种跳转方式
const goToSetname = () => {
window.location.href = '/setname';
};

map()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const products = [
{ title: 'Cabbage', isFruit: false, id: 1 },
{ title: 'Garlic', isFruit: false, id: 2 },
{ title: 'Apple', isFruit: true, id: 3 },
];

export default function ShoppingList() {
const listItems = products.map(product =>
<li
key={product.id}
style={{
color: product.isFruit ? 'magenta' : 'darkgreen'
}}
>
{product.title}
</li>
);

return (
<ul>{listItems}</ul>
);
}

类组件

  • 类组件通过扩展 React.ComponentReact.PureComponent 类来创建。
  • 它们拥有生命周期方法,如 componentDidMountcomponentDidUpdate 等,用于执行组件在不同生命周期阶段的操作。
  • 类组件可以持有状态(通过 this.state)并通过 this.setState 方法来更新状态。
函数组件

函数组件是一个纯函数,它接收 props 作为参数并返回 React 元素。

1
2
3
4
5
function MyComponent(props) 
{
return <div>Hello {props.name}</div>;
}
//一个个体,每个props独立
函数

在组件内部,函数常用作事件处理器,例如 onClickonChange

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export default function MyApp() {
const [count, setCount] = useState(0);

function handleClick() {
setCount(count + 1);
}

return (
<div>
<button count={count} onClick={handleClick}></button>
<button count={count} onClick={handleClick}></button>
</div>
);
}//整体,两个count同步


onClick={() => setCount(count + 1)}//简化
hook
1
2
3
4
5
6
7
8
const [count, setCount] = useState(0);

useEffect(() => {
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});

useContext 允许你订阅 React 上下文,而无需引入嵌套:

1
2
3
function Example() {
const locale = useContext(LocaleContext); const theme = useContext(ThemeContext); // ...
}

useReducer 允许你用 reducer 管理复杂组件的本地 state:

1
2
function Todos() {
const [todos, dispatch] = useReducer(todosReducer); // ...

swr

1

use effect和swr的渲染区别

1. useEffect 的基本用途

useEffect 是 React 的一个内置钩子,用于在组件渲染后执行副作用操作,如数据请求、订阅或手动更改DOM。它的工作方式如下:

  • 无缓存机制useEffect 自身不提供数据缓存。每次依赖项改变时,副作用都会重新执行。
  • 手动处理依赖:必须手动指定依赖项,以确定何时重新运行效果。
  • 控制副作用的执行时机:可以通过清理函数来取消副作用,例如取消网络请求或清理订阅。
2. swr 的高级特性

swr(由 Vercel 开发,名称来源于 “stale-while-revalidate”)是一个用于数据获取的 React 钩子库。它提供了许多优化的功能,特别适合于数据请求和状态管理:

  • 内建缓存和重用机制swr 自动缓存每次请求的数据,并在相同的请求再次发起时重用这些数据。这减少了不必要的网络请求和数据加载时间。
  • 后台更新:依据 “stale-while-revalidate” 的策略,swr 会在显示旧数据的同时后台更新数据,一旦新数据到达立即替换,这样用户总是看到尽可能新的数据,同时避免了界面的不必要重渲染。
  • 自动重新验证:当窗口重新获得焦点或网络状态改变时,swr 会自动重新验证数据,确保数据的实时性。
  • 更智能的依赖管理:不需要像 useEffect 那样手动声明依赖项,swr 通过请求的键(通常是 URL)自动管理依赖和更新。

context

在典型的 React 应用程序中,数据是通过 props 自上而下(父到子)传递的,但对于应用程序中许多组件所需的某些类型的 props(例如语言环境首选项、UI 主题)来说,这种使用可能会很麻烦。

Context 提供了一种在组件之间共享此类值的方法,而无需在树的每一层显式传递 prop。Context 提供了一种在组件树中共享值(如认证状态、主题、语言设置等)的方法,而无需显式地通过每个组件逐层传递 props。Context 设计的主要目的是为了全局数据(例如用户登录信息、主题或首选语言)的共享,这些数据对于应用内许多组件来说是通用的。

定义风格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export const themes = {
light: {
foreground: '#000000',
background: '#eeeeee',
},
dark: {
foreground: '#ffffff',
background: '#222222',
},
};

export const MyContext = React.createContext(
themes.dark // default value
);

创建 Context

  • 使用 React.createContext() 创建一个 Context 对象。你可以给它一个默认值。
1
const MyContext = React.createContext(defaultValue);

提供 Context 值

  • 使用 <MyContext.Provider> 包裹你的组件树中的一个高层组件。所有在这个 Provider 组件下的子组件都能访问到 Context 的值。
  • Provider 组件用于将 Context 的值传递给其组件树中的消费者(即 Consumer 组件)。它允许你定义 Context 数据的范围,这些数据可以被其下层的所有组件访问。
    • 定义数据范围Provider 接受一个 value 属性,该属性可以是任何数据类型,这个值将被提供给所有的下级 Consumer 组件。
    • 动态数据共享:你可以根据应用的需要,动态改变 Providervalue,所有依赖这个 Context 的 Consumer 会自动重新渲染,反映最新的数据。
1
2
3
<MyContext.Provider value={/* some value */}>
{children}
</MyContext.Provider>

消费 Context 值

考虑一个应用有多个主题风格,用户可以选择不同的主题风格。你可以创建一个包含当前主题信息的 Context,并在顶层组件(如 App 组件)中提供这个值。然后,在任何子组件中,无论它们位于组件树的哪一层,都可以通过上述任一方法消费这个 Context,根据当前主题进行样式调整。

  • 子组件可以通过两种方式访问 Context:

    • Context.Consumer 组件:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <MyContext.Consumer>
    {value => (
    <div style={{ backgroundColor: value.background, color: value.foreground }}>
    Text with theme colors
    </div>
    )}
    </MyContext.Consumer>

    <ThemeContext.Consumer>
    {theme => (
    <UserContext.Consumer>
    {user => (
    <ProfilePage user={user} theme={theme} />
    )}
    </UserContext.Consumer>
    )}
    </ThemeContext.Consumer>//嵌套
    • useContext 钩子(只能在函数组件中使用):
    1
    const value = useContext(MyContext);
  • lazy 允许你延迟加载组件,直到该组件需要第一次被渲染。

  • memo 允许你在 props 没有变化的情况下跳过组件的重渲染。通常 useMemouseCallback 会一起配合使用。

###好用的组件