写在最前
看官们好,我叫JetTsang,最近会尝试翻译一些外网文章,如有错误欢迎批评指正,如有歧义以原文为主。
免责声明
免责声明:
本文仅供参考和学习之用。除非另有说明,本文中引用的所有文字、图片、图表和其他媒体素材均属于其各自的版权所有者。这些材料仅出于说明和教育目的被使用,并不构成对其版权所有者的认可或推荐。
如果您是版权所有者,认为本文中的内容侵犯了您的版权,请您与我们联系。我们将配合调查并根据相关法律和规定采取适当的措施进行处理。
最后,我们保留对本文内容进行修改、更新和更正的权利。我们建议读者在阅读本文的同时,尊重他人的知识产权,遵守适用的法律和规定。
谢谢!
原文地址:How to Use React Hooks -- useEffect, useState, and useContext Code Examples (freecodecamp.org)
正文
React 是一个强大的Javascript库,它用于搭建用户界面。同时它近些年来有了翻天覆地的变化
其中最值得注意的添加就是hooks的引入,它彻底改变了开发者在函数式组件当中管理state和副作用的方式。
在这篇指南里对于新手们,我们将会探索3个最基础的hooks:useState
, useEffect
, 和 useContext
。
React Hooks 的介绍
在有hooks之前,在React当中对状态处理的逻辑主要是使用 类组件
伴随着函数式组件和hooks的出现,开发者们获得了更好的方式去处理状态和生命周期函数。Hooks 允许你在不写类的情况下去使用状态和其他的React特性
什么是React Hooks
React hooks 是一系列的函数,可以让你在函数式组件当中去那些以往只能用在类组件当中的状态,生命周期特性。
它们在React 16.8被引入,用来提供一个更连贯的方式在函数组件当中去管理状态的逻辑
如何使用 useState
useState
可能是在react当中最基础和重要的hook。它让你能在函数组件当中添加状态,让它们能追踪数据的随着时间变化。让我们通过一个简单的例子去探索useState
是如何工作的。
基础的使用
jsx
import React, { useState } from 'react';
const Counter = () => {
// 声明1个count的状态变量,并且初始化它的值为0
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
export default Counter;
在这个例子当中,我们从React
库当中引入了 useState
这个hook 这个useState
函数将会返回1个有2个元素的数组:当前的状态值(count
)和1个用于更新它的函数(setCount
)。 我们初始化count
为0,同时点击"Increment"按钮去增加它的值。
如何多次使用useState
你可以多次使用useState这个hook在同一个组件当中去独立地管理不同的state 改变一下我们的Counter
组件去添加第二个状态
jsx
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
const [isEven, setIsEven] = useState(false);
return (
<div>
<p>Count: {count}</p>
<p>{isEven ? 'Even' : 'Odd'}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setIsEven(!isEven)}>Toggle Even/Odd</button>
</div>
);
};
export default Counter;
现在我们的Counter
组件有了2个独立的状态:count
and isEven
。 点击"Toggle Even/Odd"按钮会改变isEven
的值。
怎么使用 useEffect
useEffect
这个hook是用来在函数式组件当中表达副作用,比如fetching 数据,订阅外部事件或者手动操作DOM。 它集合了componentDidMount
, componentDidUpdate
, 和 componentWillUnmount
的功能
基础使用
jsx
import React, { useState, useEffect } from 'react';
const DataFetcher = () => {
const [data, setData] = useState(null);
useEffect(() => {
// Fetch data from an API
fetch('https://api.example.com/data')
.then((response) => response.json())
.then((result) => setData(result))
.catch((error) => console.error('Error fetching data:', error));
}, []);
// 空的依赖数组代表这个副作用只会在初始渲染后只执行一次
return (
<div>
{data ? (
<ul>
{data.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
) : (
<p>Loading data...</p>
)}
</div>
);
};
export default DataFetcher;
在这个例子当中,当组件挂载时,useEffect这个hook被用来从API请求数据。useEffect的第二个参数是一个依赖数组。如果这个依赖在渲染之间发生了变化,这个副作用会被再次执行。而一个空的依赖数组意味着这个副作用只会在初始渲染之后执行一次
在useEffect当中清理
有时候副作用需要被清除,特别要在处理订阅和定时器去避免内存溢出
useEffect 返回一个清理函数,它会在这个组件卸载时被执行。
jsx
import React, { useState, useEffect } from 'react';
const Timer = () => {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setSeconds((prevSeconds) => prevSeconds + 1);
}, 1000);
// Cleanup function to clear the interval when the component unmounts
return () => clearInterval(intervalId);
}, []); // Empty dependency array for initial setup only
return <p>Seconds: {seconds}</p>;
};
export default Timer;
在这个例子当中,这个定时器被用于每秒更新seconds这个state。
在useEffect当中返回的清除函数在当这个组件被卸载时,会清空了这个定时器。
怎么使用 useContext
useContext
这个hook是用于在React当中传递自定义的值。
它提供了一种方式能在组件树的每一个层级当中手动传递props
让我们通过一个简单的例子来探索这个hooks是怎么工作的吧
如何去创建1个Context
首先,让我们创建一个contetxt来保持用户的身份验证状态。
jsx
import React, { createContext, useContext, useState } from 'react';
const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const login = () => {
setIsAuthenticated(true);
};
const logout = () => {
setIsAuthenticated(false);
};
return (
<AuthContext.Provider value={{ isAuthenticated, login, logout }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => {
return useContext(AuthContext);
};
在这个例子当中,我们通过createContext
创建了AuthContext
, 然后提供了1个AuthProvider
组件,这个组件使用context provider和包括用于login和logout的函数包裹它的children。
如何去使用useContext
现在,让我在组件当中去使用useContext
去访问 身份验证 状态
jsx
import React from 'react';
import { useAuth } from './AuthContext';
const AuthStatus = () => {
const { isAuthenticated, login, logout } = useAuth();
return (
<div>
<p>User is {isAuthenticated ? 'logged in' : 'logged out'}</p>
<button onClick={login}>Login</button>
<button onClick={logout}>Logout</button>
</div>
);
};
export default AuthStatus;
在这里, useAuth
这个hook被用于访问AuthContext
提供的值。AuthStatus
组件展示了用户的登录状态以及提供了用于登录/登出的按钮。
全部放在一起使用
让我们创建一个更加复杂的例子:将useState
, useEffect
, and useContext
组合在一个组件当中。假定有这样一个组件:从API取来用户数据并且展示出来,同时考虑到用户的身份验证状态。
jsx
import React, { useState, useEffect } from 'react';
import { useAuth } from './AuthContext';
const UserProfile = () => {
const { isAuthenticated } = useAuth();
const [userData, setUserData] = useState(null);
useEffect(() => {
if (isAuthenticated) {
// Fetch user data when authenticated
fetch('https://api.example.com/user')
.then((response) => response.json())
.then((result) => setUserData(result))
.catch((error) => console.error('Error fetching user data:', error));
}
}, [isAuthenticated]); // Run the effect when isAuthenticated changes
return (
<div>
{isAuthenticated ? (
<div>
<h2>Welcome, {userData ? userData.name : 'User'}!</h2>
<p>Email: {userData ? userData.email : 'Loading...'}</p>
</div>
) : (
<p>Please log in to view your profile.</p>
)}
</div>
);
};
export default UserProfile;
在这个例子当中, 使用了useAuth
这个hook取检查用户的身份验证状态。如果身份验证了,将会去获取用户信息同时展示个性化的欢迎信息。如果没有验证,则提示用户去登录
总结
React hooks 通过提供了更加灵活和符合直觉的方法去管理状态和副作用,从而转变了开发者写组件的方式。
当你继续和React的旅程时,精通这些hooks会增强你编写更高效和可维护的应用
记住,熟能生巧是掌握react hooks的秘籍。尝试不同的场景,探索其他的hooks,比如useReducer
and useCallback
,保持关注 React文档上任何的新特性和最佳实践。