简介
在面试 React 前端开发人员职位时,为技术问题做好充分准备至关重要。React 已经成为构建用户界面最流行的 JavaScript 库之一,雇主通常注重评估候选人对 React 核心概念、最佳实践和相关技术的理解。在本文中,我们将探讨 React 前端开发人员面试期间常见问题的完整列表。通过熟悉这些问题及其答案,您可以增加成功的机会并展示您在 React 开发方面的熟练程度。因此,让我们深入探讨您应该准备好在 React 前端开发人员面试中解决的关键主题。
1.你知道哪些React hooks?
useState:用于管理功能组件中的状态。
useEffect:用于在功能组件中执行副作用,例如获取数据或订阅事件。
useContext:用于访问功能组件内的 React 上下文的值。
useRef:用于创建对跨渲染持续存在的元素或值的可变引用。
useCallback:用于记忆函数以防止不必要的重新渲染。
useMemo:用于记忆值,通过缓存昂贵的计算来提高性能。
useReducer:用于通过reducer函数管理状态,类似于Redux的工作原理。
useLayoutEffect:与useEffect类似,但效果在所有DOM突变后同步运行。
这些钩子提供了强大的工具来管理状态、处理副作用以及重用 React 功能组件中的逻辑。
了解更多(https://react.dev/reference/react)
2.什么是虚拟DOM?
虚拟 DOM 是 React 中的一个概念,其中创建实际 DOM(文档对象模型)的轻量级虚拟表示并将其存储在内存中。它是一种用于优化 Web 应用程序性能的编程技术。
当 React 组件的数据或状态发生更改时,虚拟 DOM 会被更新,而不是直接操作真实 DOM。然后,虚拟 DOM 计算组件的先前状态和更新状态之间的差异,称为“比较”过程。
一旦识别出差异,React 就会高效地仅更新真实 DOM 的必要部分以反映更改。这种方法最大限度地减少了实际 DOM 操作的数量,并提高了应用程序的整体性能。
通过使用虚拟 DOM,React 提供了一种创建动态和交互式用户界面的方法,同时确保最佳效率和渲染速度。
3. 如何渲染元素数组?
要渲染元素数组,您可以使用该map()方法迭代该数组并返回一个新的 React 元素数组。
const languages = [ "JavaScript", "TypeScript", "Python", ]; function App() { return ( <div> <ul>{languages.map((language) => <li>{language}</li>)}</ul> </div> ); }
了解更多(https://react.dev/learn/rendering-lists)
4. 受控组件和非受控组件有什么区别?
受控组件和非受控组件之间的区别在于它们如何管理和更新其状态。
受控组件是状态由 React 控制的组件。组件接收其当前值并通过 props 更新它。当值改变时它也会触发回调函数。这意味着该组件不存储其自己的内部状态。相反,父组件管理该值并将其传递给受控组件。
import { useState } from 'react'; function App() { const [value, setValue] = useState(''); return ( <div> <h3>Controlled Component</h3> <input name="name" value={name} onChange={(e) => setValue(e.target.value)} /> <button onClick={() => console.log(value)}>Get Value</button> </div> ); }
另一方面,不受控制的组件使用 refs 或其他方法在内部管理自己的状态。它们独立存储和更新状态,不依赖 props 或回调。父组件对不受控组件的状态控制较少。
import { useRef } from 'react'; function App() { const inputRef = useRef(null); return ( <div className="App"> <h3>Uncontrolled Component</h3> <input type="text" name="name" ref={inputRef} /> <button onClick={() => console.log(inputRef.current.value)}>Get Value</button> </div> ); }
了解更多(https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components)
5. 基于类的 React 组件和函数式 React 组件有什么区别?
基于类的组件和函数组件之间的主要区别在于它们的定义方式和使用的语法。
基于类的组件被定义为 ES6 类并扩展该类React.Component。他们使用该render方法返回定义组件输出的 JSX (JavaScript XML)。this.state类组件可以通过和访问组件生命周期方法和状态管理this.setState()。
class App extends React.Component { state = { value: 0, }; handleAgeChange = () => { this.setState({ value: this.state.value + 1 }); }; render() { return ( <> <p>Value is {this.state.value}</p> <button onClick={this.handleAgeChange}> Increment value </button> </> ); } }
另一方面,函数组件被定义为简单的 JavaScript 函数。他们接受 props 作为参数并直接返回 JSX。功能组件无权访问生命周期方法或状态。然而,随着 React 16.8 中 React Hooks 的引入,功能组件现在可以管理状态并使用其他功能,例如上下文和效果。
import { useState } from 'react'; const App = () => { const [value, setValue] = useState(0); const handleAgeChange = () => { setValue(value + 1); }; return ( <> <p>Value is {value}</p> <button onClick={handleAgeChange}> Increment value </button> </> ); }
一般来说,功能组件被认为更简单、更容易阅读和测试。建议尽可能使用函数式组件,除非有特定需要基于类的组件。
6. 组件的生命周期方法有哪些?
生命周期方法是一种挂钩组件生命周期不同阶段的方法,允许您在特定时间执行特定代码。
以下是主要生命周期方法的列表:
constructor:这是创建组件时调用的第一个方法。它用于初始化状态和绑定事件处理程序。在功能组件中,您可以将useState钩子用于类似的目的。
render:该方法负责渲染 JSX 标记并返回要在屏幕上显示的内容。
componentDidMount:组件在 DOM 中渲染后立即调用此方法。它通常用于初始化任务,例如 API 调用或设置事件侦听器。
componentDidUpdate:当组件的 props 或 state 改变时调用此方法。它允许您执行副作用、根据更改更新组件或触发其他 API 调用。
componentWillUnmount:在组件从 DOM 中删除之前调用此方法。它用于清理在 中设置的任何资源componentDidMount,例如删除事件侦听器或取消计时器。
一些生命周期方法,如componentWillMount、componentWillReceiveProps和componentWillUpdate,已被弃用或替换为替代方法或挂钩。
至于“this”,它指的是类组件的当前实例。它允许您访问组件内的属性和方法。在函数式组件中,不使用“this”,因为函数未绑定到特定实例。
7. 使用useState有什么特点?
useState返回一个状态值和一个更新它的函数。
const [value, setValue] = useState('Some state');
在初始渲染期间,返回的状态与作为第一个参数传递的值匹配。该setState函数用于更新状态。它采用新的状态值作为参数,并对组件的重新渲染进行排队。该setState函数还可以接受回调函数作为参数,该函数将之前的状态值作为参数。
了解更多(https://react.dev/reference/react/useState)
8. 使用useEffect有什么特点?
钩子useEffect允许您在功能组件中执行副作用。
称为 React 渲染阶段的功能组件的主体内部不允许出现突变、订阅、计时器、日志记录和其他副作用。这可能会导致用户界面中出现令人困惑的错误和不一致。
相反,建议使用 useEffect。传递给 useEffect 的函数将在渲染提交到屏幕后执行,或者如果您传递一组依赖项作为第二个参数,则每次依赖项之一发生更改时都会调用该函数。
useEffect(() => { console.log('Logging something'); }, [])
了解更多(https://react.dev/reference/react/useEffect)
9. 如何跟踪功能组件的卸载?
通常,useEffect创建在组件离开屏幕之前需要清理或重置的资源,例如订阅或计时器标识符。
为了做到这一点,传递给的函数useEffect可以返回一个清理函数。清理函数在组件从用户界面删除之前运行,以防止内存泄漏。此外,如果组件渲染多次(通常是这种情况),则在执行下一个效果之前会清除上一个效果。
useEffect(() => { function handleChange(value) { setValue(value); } SomeAPI.doFunction(id, handleChange); return function cleanup() { SomeAPI.undoFunction(id, handleChange); }; })
10. React 中的 props 是什么?
Props 是从父组件传递给组件的数据。道具
是只读的,无法更改。
// Parent component const Parent = () => { const data = "Hello, World!"; return ( <div> <Child data={data} /> </div> ); }; // Child component const Child = ({ data }) => { return <div>{data}</div>; };
了解更多(https://react.dev/learn/passing-props-to-a-component)
11. 什么是状态管理器?您曾与哪些状态管理器共事过或认识哪些状态管理器?
状态管理器是帮助管理应用程序状态的工具或库。它提供了一个集中存储或容器来存储和管理可由应用程序中的不同组件访问和更新的数据。
状态管理器可以解决几个问题。首先,将数据和与其相关的逻辑与组件分离是一个很好的实践。其次,当使用本地状态并在组件之间传递它时,由于组件可能存在深层嵌套,代码可能会变得复杂。通过拥有全局存储,我们可以访问和修改来自任何组件的数据。
除了 React Context,Redux 或 MobX 通常用作状态管理库。
了解更多(https://mobx.js.org/README.html)和(https://redux-toolkit.js.org/)
12. 在什么情况下可以使用本地状态,什么时候应该使用全局状态?
如果本地状态仅在一个组件中使用并且不打算将其传递给其他组件,则建议使用本地状态。本地状态也用在表示列表中单个项目的组件中。但是,如果组件分解涉及嵌套组件且数据沿层次结构传递,则最好使用全局状态。
13. Redux中的reducer是什么,它有哪些参数?
减速器是一个以状态和操作作为参数的纯函数。在减速器内部,我们跟踪接收到的操作的类型,并根据它修改状态并返回一个新的状态对象。
export default function appReducer(state = initialState, action) { // 减速器通常查看操作类型字段来决定发生什么 switch (action.type) { // 根据不同类型的操作在这里做一些事情 default: // 如果此减速器无法识别操作类型,或者不 // 关心这个特定的动作,返回现有状态不变 return state } }
了解更多(https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers)
14. 什么是 Action,如何更改 Redux 中的状态?
Action 是一个简单的 JavaScript 对象,必须有一个
类型字段。
{ type: "SOME_TYPE" }
您还可以选择添加一些数据作为有效负载。为了
改变状态,需要调用dispatch函数,我们将
action传递给它
{ type: "SOME_TYPE", payload: "Any payload", }
了解更多(https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers)
15. Redux 实现了哪种模式?
Redux 实现了Flux 模式,它是应用程序的可预测状态管理模式。它通过引入单向数据流和应用程序状态的集中存储来帮助管理应用程序的状态。
了解更多(https://www.newline.co/fullstack-react/30-days-of-react/day-18/#:~:text=Flux%20is%20a%20pattern%20for,default%20method%20for%20handling%20data.)
16. Mobx 实现哪种模式?
Mobx 实现了观察者模式,也称为发布-订阅模式。
了解更多(https://www.patterns.dev/posts/observer-pattern)
17. 使用 Mobx 的特点是什么?
Mobx 提供了类似observable和的装饰器computed来定义可观察的状态和反应函数。用action修饰的动作用于修改状态,确保跟踪所有更改。Mobx 还提供自动依赖跟踪、不同类型的反应、对反应性的细粒度控制,以及通过 mobx-react 包与 React 无缝集成。总体而言,Mobx 通过根据可观察状态的变化自动执行更新过程来简化状态管理。
18. 如何访问Mobx状态下的变量?
observable您可以通过使用装饰器将变量定义为可观察来访问状态中的变量。这是一个例子:
import { observable, computed } from 'mobx'; class MyStore { @observable myVariable = 'Hello Mobx'; @computed get capitalizedVariable() { return this.myVariable.toUpperCase(); } } const store = new MyStore(); console.log(store.capitalizedVariable); // 输出:HELLO MOBX store.myVariable = 'Hi Mobx'; console.log(store.capitalizedVariable); //输出 : HI MOBX
在此示例中,myVariable被定义为使用装饰器的可观察对象observable。然后您可以使用访问该变量store.myVariable。所做的任何更改myVariable都会自动触发相关组件或反应的更新。
了解更多(https://mobx.js.org/actions.html)
19.Redux和Mobx有什么区别?
Redux 是一个更简单、更固执己见的状态管理库,遵循严格的单向数据流并促进不变性。它需要更多的样板代码和显式更新,但与 React 具有出色的集成。
另一方面,Mobx 提供了更灵活、更直观的 API,并且样板代码更少。它允许您直接修改状态并自动跟踪更改以获得更好的性能。Redux 和 Mobx 之间的选择取决于您的具体需求和偏好。
20.什么是JSX?
默认情况下,以下语法用于在 React 中创建元素。
const someElement = React.createElement( 'h3', {className: 'title__value'}, 'Some Title Value' );
但我们已经习惯这样看
const someElement = ( <h3 className='title__value'>Some Title Value</h3> );
这正是标记所谓的 jsx。这是一种语言扩展
,简化了代码和开发的感知 了解
更多(https://react.dev/learn/writing-markup-with-jsx#jsx-putting-markup-into-javascript)
21.什么是道具钻探?
Props 钻取是指通过多层嵌套组件传递 props 的过程,即使某些中间组件不直接使用这些 props。这可能会导致代码结构复杂且繁琐。
// 父组件 const Parent = () => { const data = "Hello, World!"; return ( <div> <ChildA data={data} /> </div> ); }; // 中级 ChildA 组建 const ChildA = ({ data }) => { return ( <div> <ChildB data={data} /> </div> ); }; // 叶 ChildB 组件 const ChildB = ({ data }) => { return <div>{data}</div>; };
在此示例中,dataprop 从 Parent 组件传递到 ChildA,然后从 ChildA 传递到 ChildB,即使 ChildA 不直接使用该 prop。当存在许多级别的嵌套或当组件树中更靠下的组件需要访问数据时,这可能会成为问题。它会使代码更难维护和理解。
可以通过使用其他模式(如上下文或状态管理库(如 Redux 或 MobX))来缓解 Props 钻探。这些方法允许组件访问数据,而不需要通过每个中间组件传递 props。
22. 如何有条件地渲染元素?
您可以使用任何条件运算符,包括三元。
return ( <div> {isVisible && <span>I'm visible!</span>} </div> );
return ( <div> {isOnline ? <span>I'm online!</span> : <span>I'm offline</span>} </div> );
if (isOnline) { element = <span>I'm online!</span>; } else { element = <span>I'm offline</span>; } return ( <div> {element} </div> );
了解更多(https://react.dev/learn/conditional-rendering)
23. useMemo 的用途是什么?它是如何工作的?
useMemo用于缓存和记忆
计算结果。
传递创建函数和依赖项数组。useMemo仅当任何依赖项的值发生更改时,才会重新计算记忆值。这种优化有助于避免
每次渲染时进行昂贵的计算。
使用第一个参数,该函数接受执行计算的回调,使用第二个依赖项数组,仅当至少一个依赖项发生更改时,该函数才会重新执行计算。
const memoValue = useMemo(() => computeFunc(paramA, paramB), [paramA, paramB]);
了解更多(https://react.dev/reference/react/useMemo)
24. useCallback 的用途是什么?它是如何工作的?
该useCallback钩子将返回回调的记忆版本,仅当依赖项之一的值发生更改时该版本才会更改。
当将回调传递给依赖链接相等性来防止不必要的渲染的优化子组件时,这非常有用。
const callbackValue = useCallback(() => computeFunc(paramA, paramB), [paramA, paramB]);
了解更多(https://react.dev/reference/react/useCallback)
25. useMemo 和 useCallback 有什么区别?
useMemo用于记忆计算结果,而useCallback用于记忆函数本身。
useMemo如果依赖项未更改,则缓存计算值并在后续渲染时返回该值。
useCallback缓存函数本身并返回相同的实例,除非依赖项已更改。
26.什么是React上下文?
React Context 是一项功能,它提供了一种通过组件树传递数据的方法,而无需在每个级别手动传递 props。它允许您创建一个全局状态,树中的任何组件都可以访问该状态,无论其位置如何。当您需要在未通过 props 直接连接的多个组件之间共享数据时,上下文非常有用。
React Context API 由三个主要部分组成:
createContext:该函数用于创建一个新的上下文对象。
Context.Provider:该组件用于向上下文提供值。它包装了需要访问该值的组件。
Context.Consumer或useContext钩子:该组件或钩子用于消耗上下文中的值。它可以在上下文提供者内的任何组件中使用。
通过使用 React Context,您可以避免道具钻探(通过多个级别的组件传递道具)并轻松管理更高级别的状态,使您的代码更有组织性和效率。
了解更多(https://react.dev/learn/passing-data-deeply-with-context)
27. useContext 的用途是什么?它是如何工作的?
在典型的 React 应用程序中,数据使用 props 从上到下(从父组件到子组件)传递。然而,这样的使用方法对于某些类型的 props
(例如,选择的语言、UI 主题)来说可能过于繁琐,必须将其传递给应用程序中的许多组件。上下文提供了一种在组件之间共享此类数据的方法,而无需通过
树的每个级别显式传递 props。 当上下文值改变
时,调用 useContext 的组件总是会重新渲染。
如果重新渲染组件的成本很高,您可以使用记忆来优化它。
const App = () => { const theme = useContext(ThemeContext); return ( <div style={{ color: theme.palette.primary.main }}> Some div </div> ); }
了解更多(https://react.dev/reference/react/useContext)
28. useRef 的用途是什么?它是如何工作的?
useRef返回一个可修改的 ref 对象,一个属性。其中的当前值由传递的参数初始化。返回的对象将在组件的整个生命周期内持续存在,并且不会因渲染而改变。
通常的用例是以命令式方式访问后代
。即使用 ref,我们可以显式引用 DOM 元素。
const App = () => { const inputRef = useRef(null); const buttonClick = () => { inputRef.current.focus(); } return ( <> <input ref={inputRef} type="text" /> <button onClick={buttonClick}>Focus on input tag</button> </> ) }
了解更多(https://react.dev/reference/react/useRef)
29. 什么是React.memo()?
React.memo()是一个高阶分量。如果您的组件始终使用不变的 props 渲染相同的内容,则可以将其包装在调用中React.memo()以在某些情况下提高性能,从而记住结果。这意味着 React 将使用上次渲染的结果,避免重新渲染。React.memo()只影响道具的变化。如果一个功能组件被包装在 React.memo 中并使用 useState、useReducer 或 useContext,那么当状态或上下文发生变化时,它将重新渲染。
import { memo } from 'react'; const MemoComponent = memo(MemoComponent = (props) => { // ... });
了解更多(https://react.dev/reference/react/memo)
30.什么是React Fragment?
从组件返回多个元素是 React 中的常见做法。片段允许您形成子元素列表,而无需在 DOM 中创建不必要的节点。
<> <OneChild /> <AnotherChild /> </> // or <React.Fragment> <OneChild /> <AnotherChild /> </React.Fragment>
了解更多(https://react.dev/reference/react/Fragment)
31.什么是React协调?
协调是一种 React 算法,用于区分一棵元素树与另一棵元素树,以确定需要替换的部分。
协调是我们过去所说的虚拟 DOM 背后的算法。这个定义听起来是这样的:当你渲染一个 React 应用程序时,描述该应用程序的元素树是在保留的内存中生成的。然后这棵树被包含在渲染环境中——例如,浏览器应用程序,它被翻译成一组 DOM 操作。当应用程序状态更新时,会生成一棵新树。将新树与前一棵树进行比较,以便准确计算并启用重绘更新的应用程序所需的操作。
了解更多(https://react.dev/learn/preserving-and-resetting-state)
32. 为什么使用map()时需要列表中的键?
这些键帮助 React 确定哪些元素已更改、
添加或删除。必须指定它们,以便 React 可以
随着时间的推移匹配数组元素。选择键的最佳方法是使用能够清楚区分列表项与其邻居的字符串。大多数情况下,您将使用数据中的 ID 作为密钥。
const languages = [ { id: 1, lang: "JavaScript", }, { id: 2, lang: "TypeScript", }, { id: 3, lang: "Python", }, ]; const App = () => { return ( <div> <ul>{languages.map((language) => ( <li key={`${language.id}_${language.lang}`}>{language.lang}</li> ))} </ul> </div> ); }
了解更多(https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key)
33. 如何在 Redux Thunk 中处理异步操作?
要使用 Redux Thunk,您需要将其作为中间件导入。动作创建者不仅应该返回一个对象,还应该返回一个以调度为参数的函数。
export const addUser = ({ firstName, lastName }) => { return dispatch => { dispatch(addUserStart()); } axios.post('https://jsonplaceholder.typicode.com/users', { firstName, lastName, completed: false }) .then(res => { dispatch(addUserSuccess(res.data)); }) .catch(error => { dispatch(addUserError(error.message)); }) }
了解更多(https://redux.js.org/usage/writing-logic-thunks)
34. 如何跟踪功能组件中对象字段的变化?
为此,您需要使用挂钩useEffect并将对象的字段作为依赖项数组传递。
useEffect(() => { console.log('Changed!') }, [obj.someField])
35.如何访问DOM元素?
引用是使用React.createRef()或useRef()钩子创建的,并通过 ref 属性附加到 React 元素。通过访问创建的引用,我们可以使用ref.current.
const App = () => { const myRef = useRef(null); const handleClick = () => { console.log(myRef.current); // Accessing the DOM element }; return ( <div> <input type="text" ref={myRef} /> <button onClick={handleClick}>Click Me</button> </div> ); } export default App;
36.什么是自定义钩子?
自定义钩子是一个允许您在不同组件之间重用逻辑的功能。它是一种封装可重用逻辑的方法,以便可以在多个组件之间轻松共享和重用。自定义挂钩是通常以单词 * use *开头的函数,并且可以根据需要调用其他挂钩。
了解更多(https://react.dev/learn/reusing-logic-with-custom-hooks)
37.什么是公共API?
在索引文件的上下文中,公共 API 通常是指向外部模块或组件公开并可访问的接口或函数。
以下是表示公共 API 的索引文件的代码示例:
// index.js export function greet(name) { return `Hello, ${name}!`; } export function calculateSum(a, b) { return a + b; }
在此示例中,index.js 文件充当公共 API,其中导出函数greet()和,并且可以通过导入函数从其他模块访问它们。calculateSum()其他模块可以导入并使用这些函数作为其实现的一部分:
// main.js import { greet, calculateSum } from './index.js'; console.log(greet('John')); // Hello, John! console.log(calculateSum(5, 3)); // 8
通过从索引文件导出特定函数,我们定义了模块的公共 API,允许其他模块使用这些函数。
38. 创建自定义钩子的规则是什么?
钩子名称以“use”开头。
如果需要,请使用现有的挂钩。
不要有条件地调用钩子。
将可重用逻辑提取到自定义挂钩中。
自定义钩子必须是纯函数。
自定义挂钩可以返回值或其他挂钩。
描述性地命名自定义挂钩。 了解更多(https://react.dev/learn/reusing-logic-with-custom-hooks)
39.什么是SSR(服务器端渲染)?
服务器端渲染(SSR)是一种用于在服务器上渲染页面并将完整渲染的页面发送到客户端进行显示的技术。它允许服务器生成网页的完整 HTML 标记(包括其动态内容),并将其作为对请求的响应发送到客户端。
在传统的客户端渲染方法中,客户端接收最小的 HTML 页面,然后向服务器发出额外的数据和资源请求,这些数据和资源用于在客户端渲染页面。这可能会导致初始页面加载时间变慢,并对搜索引擎优化 (SEO) 产生负面影响,因为搜索引擎爬虫很难对 JavaScript 驱动的内容建立索引。
通过 SSR,服务器通过执行必要的 JavaScript 代码来生成最终的 HTML 来负责渲染网页。这意味着客户端从服务器接收完全呈现的页面,从而减少了额外资源请求的需要。SSR 缩短了初始页面加载时间,并允许搜索引擎轻松索引内容,从而实现更好的 SEO。
SSR 通常用于框架和库中,例如用于 React 的 Next.js 和用于 Vue.js 的 Nuxt.js,以启用服务器端渲染功能。这些框架为您处理服务器端渲染逻辑,使实现 SSR 变得更加容易。
40.使用SSR有什么好处?
改进的初始加载时间:SSR 允许服务器将完全渲染的 HTML 页面发送到客户端,从而减少客户端所需的处理量。这可以缩短初始加载时间,因为用户可以更快地看到完整的页面。
SEO友好:搜索引擎可以有效地抓取和索引SSR页面的内容,因为完全渲染的HTML在初始响应中可用。这提高了搜索引擎的可见性并有助于更好的搜索排名。
可访问性:SSR 确保禁用 JavaScript 或使用辅助技术的用户可以访问内容。通过在服务器上生成 HTML,SSR 为所有用户提供可靠且易于访问的用户体验。
低带宽环境下的性能:SSR减少了客户端需要下载的数据量,对低带宽或高延迟环境下的用户有利。这对于移动用户或互联网连接速度较慢的用户尤其重要。
虽然 SSR 提供了这些优势,但值得注意的是,与客户端渲染方法相比,它可能会带来更多的服务器负载和维护复杂性。应仔细考虑缓存、可扩展性和服务器端渲染性能优化等因素。
41.你知道Next.js的主要功能有哪些?
1、getStaticProps:此方法用于在构建时获取数据并将页面预渲染为静态 HTML。它确保数据在构建时可用,并且不会因后续请求而更改。
export async function getStaticProps() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return { props: { data } }; }
2、getServerSideProps:该方法用于在每次请求时获取数据并在服务器上预渲染页面。当您需要获取可能经常更改或特定于用户的数据时,可以使用它。
export async function getServerSideProps() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return { props: { data } }; }
3、getStaticPaths:此方法用于动态路由中,以指定应在构建时预渲染的路径列表。它通常用于获取带有参数的动态路由的数据。
export async function getStaticPaths() { const res = await fetch('https://api.example.com/posts'); const posts = await res.json(); const paths = posts.map((post) => ({ params: { id: post.id } })); return { paths, fallback: false }; }
了解更多(https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating)
42.什么是短绒?
Linters 是用于检查源代码是否存在潜在错误、错误、风格不一致和可维护性问题的工具。它们帮助执行编码标准并确保整个代码库的代码质量和一致性。
Linters 的工作原理是扫描源代码并将其与一组预定义的规则或指南进行比较。这些规则可以包括语法和格式约定、最佳实践、潜在错误和代码异味。当 linter 发现违反规则时,它会生成警告或错误,突出显示需要注意的特定行或多行代码。
使用 linter 可以带来几个好处:
代码质量:Linter 有助于识别和防止潜在的错误、代码异味和反模式,从而提高代码质量。
一致性:Linter 强制执行编码约定和风格指南,确保整个代码库的格式和代码结构一致,即使多个开发人员正在处理同一个项目时也是如此。
可维护性:通过尽早发现问题并促进良好的编码实践,linter 有助于代码的可维护性,使理解、修改和扩展代码库变得更容易。
效率:Linter 可以通过自动化代码审查流程并在常见错误在开发或生产过程中引起问题之前发现它们,从而节省开发人员的时间。
一些流行的 linter 包括用于 JavaScript 的 ESLint 以及用于 CSS 和 Sass 的 Stylelint。
了解更多(https://eslint.org/docs/latest/use/getting-started)
43. 你知道哪些 React 架构解决方案?
有多种用于构建 React 项目的架构解决方案和模式。一些受欢迎的包括:
MVC(模型-视图-控制器):MVC 是一种传统的架构模式,它将应用程序分为三个主要组件 - 模型、视图和控制器。React 可以在 View 层中使用来渲染 UI,而其他库或框架可以用于 Model 和 Controller 层。
Flux:Flux是Facebook专门针对React应用程序推出的应用程序架构。它遵循单向数据流,其中数据沿单个方向流动,从而更容易理解和调试应用程序的状态更改。
原子设计:原子设计并不是 React 特有的,而是一种将 UI 划分为更小、可重用组件的设计方法。它鼓励构建小型、独立且可以组合以创建更复杂的 UI 的组件。
容器和组件模式:该模式将表示(组件)与逻辑和状态管理(容器)分开。组件负责渲染 UI,而容器则处理业务逻辑和状态管理。
功能切片设计:它是一种用于组织和构建 React 应用程序的现代架构方法。它旨在通过根据功能或模块划分应用程序代码库来解决可扩展性、可维护性和可重用性的挑战。
44.什么是特征切片设计?
它是一种用于组织和构建 React 应用程序的现代架构方法。它旨在通过根据功能或模块划分应用程序代码库来解决可扩展性、可维护性和可重用性的挑战。
在功能切片设计中,应用程序的每个功能或模块都组织到一个单独的目录中,其中包含所有必要的组件、操作、reducers 和其他相关文件。这有助于保持代码库的模块化和隔离性,使其更易于开发、测试和维护。
功能切片设计促进了关注点的清晰分离,并将功能封装在各个功能中。这允许不同的团队或开发人员独立地处理不同的功能,而不必担心冲突或依赖性。
还有就是可以去了解功能切片设计
文章来源:https://www.toymoban.com/diary/mianshi/397.html
文章来源地址https://www.toymoban.com/diary/mianshi/397.html
到此这篇关于44个常见的React前端面试问题的文章就介绍到这了,更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!