面试题答案
一键面试利用Context传递数据
- 创建Context对象:
在项目合适位置(通常是顶层)创建Context对象,例如:
import React from 'react'; const MyContext = React.createContext(); export default MyContext;
- 在A组件中提供数据:
A组件引入
MyContext
,通过MyContext.Provider
将数据传递下去,示例代码如下:import React from'react'; import MyContext from './MyContext'; class A extends React.Component { constructor(props) { super(props); this.state = { dataToPass: '初始数据' }; } render() { return ( <MyContext.Provider value={this.state.dataToPass}> {/* 这里渲染B组件 */} <B /> </MyContext.Provider> ); } }
- 在E组件中消费数据:
E组件引入
MyContext
,使用MyContext.Consumer
或者useContext
Hook来获取数据。- 使用
MyContext.Consumer
:
import React from'react'; import MyContext from './MyContext'; class E extends React.Component { render() { return ( <MyContext.Consumer> {data => ( <div>{data}</div> )} </MyContext.Consumer> ); } }
- 使用
useContext
Hook(适用于函数式组件):
import React, { useContext } from'react'; import MyContext from './MyContext'; const E = () => { const data = useContext(MyContext); return <div>{data}</div>; };
- 使用
保证数据更新时E组件重新渲染
当A组件中的数据更新时,例如通过setState
改变dataToPass
,由于MyContext.Provider
的value
属性发生了变化,依赖这个Context的所有组件(包括E组件)都会重新渲染。
可能遇到的性能问题及解决方案
- 性能问题:
- 不必要的重新渲染:因为Context的变化会导致所有使用该Context的组件重新渲染,即使中间组件(如B、C、D)的props和state没有变化,也会重新渲染,这可能会带来性能开销。
- 解决方案:
- 使用React.memo或shouldComponentUpdate:
- 对于函数式组件,可以使用
React.memo
包裹中间组件(B、C、D),它会对组件的props进行浅比较,如果props没有变化,组件不会重新渲染。例如:
const B = React.memo((props) => { // B组件逻辑 return <div>{/* B组件渲染内容 */}</div>; });
- 对于类组件,可以在中间组件(B、C、D)中实现
shouldComponentUpdate
方法,手动控制组件是否重新渲染。例如:
class B extends React.Component { shouldComponentUpdate(nextProps, nextState) { // 在这里比较当前props/state和nextProps/nextState // 如果不需要更新则返回false return true; } render() { return <div>{/* B组件渲染内容 */}</div>; } }
- 对于函数式组件,可以使用
- 使用useReducer和Context结合:可以将Context和
useReducer
结合,通过dispatch更细粒度地控制数据更新,避免不必要的重新渲染。例如,在A组件中使用useReducer
管理数据状态,通过dispatch传递更有针对性的更新动作,这样只有依赖特定更新动作的组件(如E组件)才会重新渲染。
- 使用React.memo或shouldComponentUpdate: