网站首页 > 基础教程 正文
ReactJs 是一个用于构建用户界面的流行 JavaScript 库。它由 Facebook 维护,广泛用于构建 Web 应用程序、移动应用程序和其他用户界面。React 允许开发人员创建可重复使用的组件,这有助于使大型应用程序更易于管理和维护。它旨在高效、声明性和灵活,可用于创建复杂、动态的用户界面。
1. React 如何工作?
React 会创建一个虚拟 DOM。当组件中的状态发生变化时,它首先会运行“diffing”算法,该算法会识别虚拟 DOM 中发生了哪些变化。第二步是协调,它会使用 diff 的结果更新 DOM。
2. 使用 React 有什么优点?
- 要知道一个组件是如何渲染的很容易,只需要看看渲染函数。
- JSX 让您能够轻松阅读组件代码。您还可以轻松查看布局或组件的插入/组合方式。
- 您可以在服务器端渲染 React。这可以改善 SEO 和性能。
- 很容易测试。
- 您可以将 React 与任何您想要的框架一起使用,因为它只是一个视图层。
3. 展示组件和容器组件有什么区别?
展示组件关注的是事物的外观。它们通常仅通过 props 接收数据和回调。这些组件很少有自己的状态,但如果有,通常与 UI 状态有关,而不是数据状态。
当你的组件只接收 props 并将它们渲染到页面时,这就是stateless component,可以使用纯函数。这些也称为哑组件或展示组件。
容器组件更关心事物的运作方式。这些组件为展示组件或其他容器组件提供数据和行为。它们定义操作并将其作为回调提供给展示组件。它们通常也是有状态的,因为它们充当数据源。
4. 类组件和功能组件有什么区别?
类组件使用 ES6 类语法,并使用返回 React 元素的 render 方法扩展 React 组件。
带有钩子的函数组件是纯 JavaScript 函数,也会返回 React 元素。在引入钩子之前,函数组件是无状态的。
5. state 和 props 有什么区别?
状态是一种数据结构,在组件安装时以默认值开始。状态可能会随时间发生变化,主要是由于用户事件。
Props(properties 的缩写)是组件的配置。它们从上方接收,并且对于接收它们的组件而言是不可变的。组件无法更改其 props,但它负责将其子组件的 props 组合在一起。回调函数也可以作为 props 传入。
6. 有哪些不同的生命周期方法?
- componentWillMount(已弃用)——这最常用于根组件中的应用程序配置。
- componentDidMount- 在这里,您需要完成所有没有 DOM 就无法完成的设置,并开始获取所需的所有数据。此外,如果您想设置事件监听器等,这个生命周期钩子是执行此操作的好地方。
- componentWillReceiveProps(已弃用) - 此生命周期作用于特定的 prop 变化来触发状态转换。
- shouldComponentUpdate- 如果您担心浪费渲染,shouldComponentUpdate 是一个提高性能的好地方,因为它允许您在组件收到新的 prop 时防止重新渲染。shouldComponentUpdate 应该始终返回一个布尔值,并根据这个布尔值确定组件是否重新渲染。
- componentWillUpdate(已弃用) - 很少使用。它可以代替 componentWillReceiveProps 用于同样具有 shouldComponentUpdate(但无法访问先前的 props)的组件。
- componentDidUpdate- 也常用于响应 prop 或状态变化来更新 DOM。
- componentWillUnmount- 使您可以取消任何传出的网络请求,或删除与该组件相关的所有事件监听器。
7.解释 React Hooks。
Hooks 可让您使用更多 React 功能,而无需使用类。您最有可能遇到的第一个 Hook 是
useState。useState 是一个 Hook,可让您将 React 状态添加到函数组件。它返回一个带有 getter 和 setter 的数组。
语法如下:
const [count, setCount] = React.useState(0);
<button onClick={() => setCount(count + 1)}>Increase Count</button>;
使用类组件时的等效效果是。
this.state = {
count: 0,
};
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Increase Count
</button>;
您最有可能遇到的下一个钩子是 useEffect。Effect Hook 允许您在函数组件中执行副作用。通过将空数组作为第二个参数传递给 useEffect 相当于使用 componentD
useEffect(() => {
// do stuff when the component mounts
}, []);
8. 应该在 React 类组件的哪里发出 AJAX/API 请求?
componentDidMount是 React 组件中应发出 AJAX 请求的位置。此方法将在组件mounts(首次添加到 DOM)时执行。此方法在组件的生命周期内仅执行一次。重要的是,您无法保证 AJAX 请求在组件挂载之前已解析。如果没有,则意味着您将尝试在未挂载的组件上设置状态,这将不起作用。发出 AJAX 请求componentDidMount将保证有一个组件要更新。
9.什么是受控组件?
在 HTML 中,表单元素(例如<input>、<textarea>和)<select>通常会保持自己的状态并根据用户输入进行更新。当用户提交表单时,上述元素的值将随表单一起发送。在 React 中,它的工作方式有所不同。包含表单的组件将跟踪其状态下的输入值,并在每次触发回调函数(例如 onChange)时重新渲染组件,因为状态将更新。以这种方式由 React 控制值的输入表单元素称为controlled component。
10. React 中的 refs 有什么用处?
Refs 用于获取对 React 中 DOM 节点或组件实例的引用。使用 refs 的典型示例包括管理焦点/文本选择、触发命令式动画或与第三方 DOM 库集成。您应避免使用字符串 refs 和内联 ref 回调。React 建议使用回调 refs。
11. 什么是高阶组件?
高阶组件是一个接受组件并返回新组件的函数。HOC 允许您重用代码、逻辑和引导抽象。最常见的可能是 Redux 的连接函数。除了简单地共享实用程序库和简单组合之外,HOC 是在 React 组件之间共享行为的最佳方式。如果您发现自己在不同的地方编写了大量执行相同操作的代码,您可能能够将该代码重构为可重用的 HOC。
12. 使用箭头函数有什么优点?
- 范围安全:在箭头函数出现之前,每个新函数都定义了自己的 this 值(如果是构造函数,则为新对象;如果是严格模式函数调用,则为未定义;如果函数被调用为“对象方法”,则为基对象,等等)。箭头函数不会创建自己的 this,而是使用封闭执行上下文的 this 值。
- 紧凑性:箭头函数更易于阅读和编写。
- 清晰度:当几乎所有东西都是箭头函数时,任何常规函数都会立即脱颖而出,用于定义范围。开发人员始终可以查找下一个上级函数语句来查看对象是什么。
13. 如何防止类组件渲染?
从组件的渲染方法返回 null 意味着不会显示任何内容,但它不会影响组件生命周期方法的触发。
如果组件重新渲染的次数是一个问题,那么有两个选项可用。在shouldComponentUpdate生命周期方法钩子中手动实现检查。
shouldComponentUpdate(nextProps, nextState){
const allowRender = true;
// Do some check here and assign decicison to allowRender
return allowRender
}
或者使用 React.PureComponent 而不是 React.Component React.PureComponent 通过浅显的 prop 和 state 比较来实现 shouldComponentUpdate()。这可以避免使用相同的 props 和 state 重新渲染组件。
14. 渲染列表时,键是什么以及它的用途是什么?
键可帮助 React 识别哪些项目已更改、已添加或已删除。应为数组内的元素指定键,以赋予元素稳定的身份。选择键的最佳方法是使用一个字符串,该字符串可唯一地标识列表项在其兄弟项中的位置。大多数情况下,您会使用数据中的 ID 作为键。当您没有渲染项目的稳定 ID 时,您可以将项目索引用作键作为最后的手段。如果项目可以重新排序,则不建议使用索引作为键,因为那样会很慢。
15.`super(props)`的用途是什么?
子类构造函数在被调用之前不能使用 this super()。此外,如果是子类,则必须调用 ES2015 类构造函数super()。将 props 传递给的原因super()是为了让你能够this.props在构造函数中访问。
16.什么是 JSX?
JSX 是 JavaScript 的语法扩展,具有 JavaScript 的全部功能。JSX 生成 React elements。
您可以将任何 JavaScript 表达式嵌入到 JSX 中,只需将其括在花括号中即可。经过编译后,JSX 表达式将成为常规 JavaScript 对象。
这意味着您可以在if语句和内部使用 JSX for loops,将其分配给变量,将其作为参数接受,并从函数中返回它。
17. 使用 React.createElement 相当于以下哪一项?
const element = <h1 className="greeting">Hello, world!</h1>;
const element = React.createElement(
"h1",
{ className: "greeting" },
"Hello, world!"
);
18.什么是redux?
- redux 的基本思想是将整个应用程序的状态保存在一个单独的存储中。该存储只是一个 javascript 对象。
- 改变状态的唯一方法是从应用程序发送操作,然后为这些修改状态的操作编写减速器。
- 整个状态转换都保存在 Reducer 内部,并且不应该有任何side-effects。
19.redux 中的 store 是什么?
- store 是一个保存应用程序状态的 JavaScript 对象。除此之外,它还具有以下职责:
- 允许通过 访问状态getState();。
- 允许通过 更新状态dispatch(action);。
- 通过 注册监听器subscribe(listener);。
- 通过 返回的函数处理监听器的取消注册subscribe(listener)。
20. 动作器 (action) 和减速器 (reducer) 的区别。
- 动作是普通的 javascript 对象。
- 它们必须具有一种类型来指示正在执行的操作的类型。
- 本质上,操作是将数据从您的应用程序发送到您的商店的信息的有效负载。
- Reducer 只是一个纯函数,它接受先前的状态和动作,并返回下一个状态。
21.Redux Thunk 用于什么?
- Redux thunk 是一个中间件,它允许您编写返回函数而不是动作的动作创建器。
- 然后,如果满足某个条件,可以使用 thunk 来延迟动作的分派。这允许您处理动作的异步分派。
22. 编写一个自定义钩子,可用于消除用户输入的抖动。
//hook
const useDebounce = (value, delay) => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timeout = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(timeout);
};
}, [value]);
return debouncedValue;
};
//example
const Counter = () => {
const [value, setValue] = useState(0);
const lastValue = useDebounce(value, 1000);
return (
<div>
<p>
Current Value: {value} | Debounced Value: {lastValue}
</p>
<button onClick={() => setValue(value + 1)}>Increment</button>
</div>
);
};
23. 编写自定义钩子以将文本复制到剪贴板。
// hook
function useCopyToClipboard(content) {
const [isCopied, setIsCopied] = useState(false);
const copy = useCallback(() => {
navigator.clipboard
.writeText(content)
.then(() => setIsCopied(true))
.then(() => setTimeout(() => setIsCopied(false), 1250))
.catch((err) => alert(err));
}, [content]);
return [isCopied, copy];
}
// usage
export default function App() {
const [isCopied, copy] = useCopyToClipboard("Text to copy!");
return <button onClick={copy}>{isCopied ? "Copied!" : "Copy"}</button>;
}
24. 如何使用“useId”Hook 生成唯一的 ID。
- useId 不接受任何参数。
- useId 返回与此特定组件中的此特定 useId 调用相关联的唯一 ID 字符串。
//usage
import { useId } from "react";
const App = () => {
const id = useId();
return (
<form>
<label htmlFor={`email-${id}`}>Email</label>
<input type="text" id={`email-${id}`} name="email" />
<label htmlFor={`password-${id}`}>Password</label>
<input type="password" id={`password-${id}`} name="password" />
</form>
);
};
// Bad Practise - Don't use for key
const id = useId();
return posts.map((post) => <article key={id}>...</article>);
25. 如何在 React 中验证 Props?
- 我们可以使用 'prop-types' 包
- 之前,直到 React v15.5,它都是 React 本身的一部分
import PropTypes from "prop-types";
function MyComponent({ name }) {
return <div>Hello, {name}</div>;
}
MyComponent.propTypes = {
name: PropTypes.string,
};
export default MyComponent;
26. 给出一个 React 中高阶组件的实例。
当组件等待数据时显示加载器
//HOC
function WithLoading(Component) {
return function WihLoadingComponent({ isLoading, ...props }) {
if (!isLoading) return <Component {...props} />;
return <p>Please wait, fetching your data in no time...</p>;
};
}
export default WithLoading;
//usage
import UserListComponent from "./UserListComponent.js"; //importing component
import WithLoading from "./withLoading.js"; //importing HOC
const ListWithLoading = WithLoading(UserListComponent); //connect component with HOC
const App = () => {
const [loading, setLoading] = useState(true);
const [users, setUsers] = useState([]);
useEffect(() => {
//fetch data
const dataFromApi = ["this is coming from API call", "don't show loader"];
//at this time loader will be shown in the UI using HOC
//data fetched successfully
setUsers([...dataFromApi]);
setLoading(false);
}, []);
return <ListWithLoading isLoading={loading} users={users} />;
};
27. 为什么 React 的 useDeferredValue 钩子很有用?
- 'useDeferredValue' 是一个 React Hook,可让您推迟更新部分 UI。
- 基本上,它让您用更少的代码执行去抖动技术。
//usage
import { useState, useDeferredValue } from "react";
//userList component takes searchText to fetch user's list
import UserList from "./UserList.js";
export default function App() {
const [searchText, setSearchText] = useState("");
//pass searchText as default visible value in useDeferredValue
const deferredQuery = useDeferredValue(searchText);
return (
<>
<label>
Search user:
<input
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
/>
</label>
<div>
<UserList searchText={deferredQuery} />
</div>
</>
);
}
29. 如何检测 React 组件外部的“点击”?
export default function OutsideAlerter() {
const clickMeDivRef = useRef(null);
useEffect(() => {
const handleClickOutside = (event) => {
if (!ref?.current?.contains(event.target)) {
alert("You clicked outside of me!");
}
};
// Bind the event listener
document.addEventListener("mousedown", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener("mousedown", handleClickOutside);
};
}, [clickMeDivRef]);
return <div ref={clickMeDivRef}>Clicked me?</div>;
}
30.为什么React组件名称必须以大写字母开头?
- 在 JSX 中,小写标签名称被视为 HTML 标签。但是,带点(属性访问器)的小写标签名称则不是。
- <person />编译为 React.createElement('person') (html 标签)
- <Person />编译为 React.createElement(Person)
- <obj.person />编译为 React.createElement(obj.person)
// Wrong! This is a component and should be in uppercase.
function person(props) {
// Correct! This usage of <div> is correct because div is a valid element.
return <div>{props.isLearning ? "Great!" : "Call Mom!"}</div>;
}
function App() {
// Wrong! React thinks <person /> is a HTML tag because it's not capitalized.
return <person isLearning={true} />;
}
// Correct! This is a component and should be capitalized
function Person(props) {
// Correct! This usage of <div> is correct because div is a valid element.
return <div>{props.isLearning ? "Great!" : "Call Mom!"}</div>;
}
function App() {
// Correct! React knows <Person /> is a component because it's capitalized.
return <Person isLearning={true} />;
}
31.npx 和 npm 有什么区别?
- NPM 是一个包管理器,可用于安装 node.js 包。
- NPX 是一个执行 node.js 包的工具。
无论您是全局安装还是本地安装该包,NPX 都会临时安装并运行它。如果您配置了 package.json 文件,NPM 也可以运行包。
因此,如果您想快速检查/运行节点包而不安装它 - 请使用 NPX。
'create-react-app' 是一个 npm 包,预计在项目生命周期中仅运行一次。因此,最好使用 npx 一步安装并运行它。
> npx create-react-app codinn
npM - Manager
npX - Execute
32. 组件安装到 UI 上后,如何将焦点设置在输入字段上?
import React, { useEffect, useRef } from "react";
const SearchPage = () => {
const textInput = useRef(null);
useEffect(() => {
textInput.current.focus();
}, []);
return (
<div>
<input ref={textInput} type="text" />
</div>
);
};
33.如何使用最新版本的 React Router 以编程方式导航?
//old - v5
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
history.push('/some/path') here
};
//new - v6+
import { useNavigate } from "react-router-dom";
function SignupForm() {
let navigate = useNavigate();
async function handleSubmit(event) {
event.preventDefault();
await submitForm(event.target);
navigate("../success", { replace: true });
}
return <form onSubmit={handleSubmit}>{/* ... */}</form>;
}
//or
import { redirect } from "react-router-dom";
const loader = async () => {
const user = await getUser();
if (!user) {
return redirect("/login");
}
};
34.什么是 React 状态批处理?猜猜输出结果。
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button
onClick={() => {
setNumber(number + 1);
setNumber(number + 1);
setNumber(number + 1);
}}
>
+3
</button>
</>
);
}
输出
- 点击 '+3' -> 打印 '1'
- 或者由于状态批处理概念,仅更新状态一次
为什么?
这使您可以更新多个状态变量而不会触发太多的重新渲染。
但如果您还是想更新呢?那就是 - 点击“+3”时需要打印 3。
将回调方法传递给setNumber。
setNumber((n) => n + 1);
return (
<>
<h1>{number}</h1>
<button
onClick={() => {
setNumber((n) => n + 1);
setNumber((n) => n + 1);
setNumber((n) => n + 1);
}}
>
+3
</button>
</>
);
35. 如何使用 React 路由器在兄弟组件之间传递数据?
使用 React Router hook 可以在 React 的兄弟组件之间传递数据useParams。
父组件(通常是 App.js 来定义路由)
<Route path="/user/:id" element={<User />} />
import { useParams } from "react-router-dom";
const User = () => {
let { id } = useParams();
useEffect(() => {
console.log(`/user/${id}`);
}, []);
// .....
};
36. 如何使用 useContext hook 访问全局变量?
//1. create context
const GlobalLanguageContext = React.createContext(null);
const App = () => {
const contextValue = { language: "EN" };
return (
//2. connect with all the child components under Provider
//One time Config - Here in Provider's value prop you can pass
//the value of your context global variable
<GlobalLanguageContext.Provider value={contextValue}>
<Child />
</GlobalLanguageContext.Provider>
);
};
const Child = () => {
//3. use variable
const { language } = React.useContext(GlobalLanguageContext);
return <div>Application Language: {language}</div>;
};
37. useMemo 和 useCallback 有什么区别?
- useCallback 为您提供函数渲染之间的引用相等性。 useMemo 为您提供值渲染之间的引用相等性。
- useCallback 和 useMemo 都要求一个函数和一个依赖项数组。区别在于,当依赖项发生变化时,useCallback 返回其函数,而 useMemo 调用其函数并返回结果。
- useCallback 返回其未调用的函数,以便您可以稍后调用它,而 useMemo 调用其函数并返回结果
38. 为什么你应该选择 vite 而不是 create-react-app?
- Create React App (CRA) 长期以来一直是大多数开发人员搭建 React 项目和设置开发服务器的首选工具。它提供了无需配置的现代构建设置。
- 但是,当项目规模增加时,我们发现开发和构建时间也会增加。这种缓慢的反馈循环会影响开发人员的生产力和幸福感。
- 为了解决这些问题,生态系统中出现了一个新的前端工具:Vite。
- 与 CRA 不同,Vite 不会在提供服务之前构建整个应用程序,而是按需构建应用程序。它还利用原生 ES 模块、esbuild 和 Rollup 的强大功能来缩短开发和构建时间。
- Vite 是新一代、注重速度和性能的前端工具。
- Vite 是一个开发服务器,它在原生 ES 模块的基础上提供了丰富的功能增强:快速热模块替换(HMR)、预捆绑、对 typescript、jsx 和动态导入的支持。
- 将您的代码与 Rollup 捆绑在一起的构建命令,已预先配置为输出用于生产的优化静态资产。
39.react-router 有什么优点?
- 主要的优点react-router是当点击另一个页面的链接时,页面不必刷新。
- 它还允许我们使用浏览器的history功能,同时保留正确的应用程序视图。
- 更好的用户体验,在不同组件之间切换时可以轻松实现动画和过渡。
- React Routerdynamic routing用于确保路由按照用户请求实现。这也意味着所有必需的组件也都呈现,不会出现任何白屏闪烁或页面重新加载。
- 主要成分有react-router:BrowserRouter,Routes,Route,Link。
40. 如何优化 ReactJS 应用程序的性能?
- 一种方法是使用 shouldComponentUpdate 生命周期方法来防止组件不必要的重新渲染。
- 另一种方法是使用 PureComponent 类,它通过对 props 和 state 进行浅比较来实现 shouldComponentUpdate。
另外,使用React.memo高阶组件可以优化功能组件的性能。
41. 在 ReactJs 中编写 CRUD 功能代码?
要使用钩子在 React 应用程序中实现 CRUD(创建、读取、更新、删除)功能,您可以使用 useState 钩子来管理应用程序的状态,并使用 useEffect 钩子来处理副作用,例如向服务器发出 API 调用来创建、读取、更新或删除数据。
下面是如何使用钩子在 React 组件中实现 CRUD 功能的示例:
import React, { useState, useEffect } from "react";
function App() {
// useState hook to manage the state of our items
const [items, setItems] = useState([]);
// useEffect hook to fetch the items from an API
useEffect(() => {
fetch("https://my-api.com/items")
.then((response) => response.json())
.then((data) => setItems(data));
}, []);
// helper function to add a new item
const addItem = (name) => {
const newItem = { name };
setItems([...items, newItem]);
};
// helper function to update an item
const updateItem = (index, name) => {
const updatedItems = [...items];
updatedItems[index] = { name };
setItems(updatedItems);
};
// helper function to delete an item
const deleteItem = (index) => {
const updatedItems = [...items];
updatedItems.splice(index, 1);
setItems(updatedItems);
};
// render the items in a list
return (
<ul>
{items.map((item, index) => (
<li key={index}>
{item.name}
<button onClick={() => updateItem(index, "updated name")}>
Update
</button>
<button onClick={() => deleteItem(index)}>Delete</button>
</li>
))}
<button onClick={() => addItem("new item")}>Add item</button>
</ul>
);
}
42. React 中的 hooks 是什么?为什么它们有用?
React 中的钩子是一种函数,它允许开发人员在不编写类的情况下使用状态和其他 React 功能。这使得可以在函数式组件中使用这些功能,与基于类的组件相比,函数式组件更容易编写和理解。
43. React 中使用哪些常见的 hooks?
React 中使用的一些常见钩子包括 useState、useEffect 和 useContext。useState 钩子允许功能组件具有本地状态,useEffect 钩子允许功能组件执行副作用,useContext 钩子允许功能组件从最近的上下文提供程序访问值。
44. 你能在基于类的组件内部使用钩子吗?
不可以,钩子只能在函数式组件中使用。如果您需要在基于类的组件中使用状态或其他 React 功能,则需要使用类组件。
45. 如何测试使用钩子的组件?
您可以使用 react-testing-library 包中的 act 实用程序来测试使用钩子的组件。此实用程序允许您模拟 React 协调过程的效果,这对于钩子正常工作必不可少。然后,您可以使用标准 Jest 或 Enzyme 断言来验证组件的行为。
46. useEffect hook 有什么用?
useEffect 钩子用于在功能组件中执行副作用。这可以包括数据获取、设置订阅或手动更改 DOM 等操作。useEffect 钩子在组件渲染后调用,可用于确保您的组件与任何相关数据或依赖项保持同步。
47.在 React 中创建一个简单的自定义钩子?
要在 React 中创建自定义钩子,可以使用 useState 钩子将本地状态添加到功能组件。以下是示例:
import { useState } from "react";
function useCounter() {
const [count, setCount] = useState(0);
function increment() {
setCount(count + 1);
}
return { count, increment };
}
此钩子为组件添加了计数状态和增量函数。要在组件中使用此钩子,您可以在组件函数顶部调用它,如下所示:
function MyComponent() {
const { count, increment } = useCounter();
return (
<div>
<p>The count is {count}.</p>
<button onClick={increment}>Increment</button>
</div>
);
}
现在,每当单击增量按钮时,计数状态都会更新,并且组件将使用新值重新渲染。
48. useEffect 和 useLayoutEffect 有什么区别?
下面是如何在 React 组件中使用 useEffect 和 useLayoutEffect 的示例:
import React, { useState, useEffect, useLayoutEffect } from "react";
function MyComponent() {
const [count, setCount] = useState(0);
// useEffect runs after the render cycle has completed
useEffect(() => {
// This code will run every time the component renders,
// after the render is complete.
console.log("useEffect running");
});
// useLayoutEffect runs synchronously immediately after the render cycle
useLayoutEffect(() => {
// This code will run every time the component renders,
// before the browser has a chance to paint the update to the screen.
// Be careful! This can cause visual inconsistencies.
console.log("useLayoutEffect running");
});
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
在此示例中,单击“增量”按钮时,useEffect 钩子将在组件更新并重新渲染后运行,而 useLayoutEffect 钩子将在更新绘制到屏幕之前运行。这意味着,如果您使用 useLayoutEffect 更新 UI,用户可能会在更新完成之前看到 UI 更新,这可能会导致视觉不一致。另一方面,useEffect 在更新完成后运行,因此用于更新 UI 更安全。
49.为什么虚拟DOM比真实DOM更新更快?
- 虚拟 DOM 比真实 DOM 更新速度更快,因为 React 使用了一种巧妙的技术来最大限度地减少需要对真实 DOM 进行的更新次数。
- 当你更新虚拟 DOM 时,React 会将新的虚拟 DOM 与旧的虚拟 DOM 进行比较,确定哪些部分发生了变化,然后相应地更新真实 DOM。这意味着只更新 DOM 中真正需要更改的部分,这比每次发生更改时更新整个 DOM 要快得多。
- 此外,虚拟 DOM 是用 JavaScript 实现的,其执行速度通常比用于操作真实 DOM 的本机代码更快。
- 这意味着 React 可以快速对虚拟 DOM 进行更新,然后使用生成的 diff 对真实 DOM 进行高效更新。
- 总的来说,使用虚拟 DOM 可以让 React 高效地更新 UI,从而带来更快、响应更快的用户体验。
50. 你能解释一下纯函数和非纯函数之间的区别吗?以及为什么它在 React 环境中很重要?
在 React 中,纯函数是指无论何时调用,对于同一组输入都会返回相同输出的函数。另一方面,非纯函数是指对于同一组输入可能会产生不同输出的函数,具体取决于调用时间或其他因素。
以下是 React 中纯函数的一个示例:
function addNumbers(a, b) {
return a + b;
}
此函数接受两个数字 a 和 b,并返回它们的和。无论何时调用或组件处于何种状态,此函数始终会针对相同的输入返回相同的结果。
以下是 React 中非纯函数的一个例子:
function getRandomNumber() {
return Math.random();
}
此函数每次调用时都会返回一个随机数。由于此函数的输出取决于其无法控制的因素(在本例中为当前时间和随机种子),因此它被视为非纯函数。
通常,React 更倾向于使用纯函数,因为它们更易于推理和测试。另一方面,非纯函数可能会引入不可预测的行为,并使您的代码更难理解。
猜你喜欢
- 2024-11-24 React源码分析与实现(一):组件的初始化与渲染「实践篇」
- 2024-11-24 React 最简单的入门应用项目
- 2024-11-24 「干货」深入浅出React组件逻辑复用的那些事儿
- 2024-11-24 「干货满满」React Hooks 最佳实践
- 2024-11-24 React开发必须知道的34个技巧
- 2024-11-24 React组件应该如何封装?
- 2024-11-24 React.js前端框架初学技术总结
- 2024-11-24 前端架构师成长之路:5 分分钟搞懂面试官必问 React 题
- 2024-11-24 只会Vue的我,用两天学会了react,这个方法您也可以
- 2024-11-24 react高质量笔记_9(Diffing算法)
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)