React状态管理常见面试题目(二)

ops/2024/12/18 18:54:39/

为什么 Redux 能做到局部渲染?

Redux能做到局部渲染,主要是因为它采用了单向数据流和状态管理机制。在Redux中,整个应用的状态被存储在一个单一的store中,当状态发生变化时,Redux通过分发action来更新state,并通过reducer函数生成新的state。组件通过订阅store中的状态来刷新自己的视图,当state中的某部分数据发生变化时,只有订阅了该部分数据的组件会重新渲染,从而实现局部渲染。

为什么 React 并不推荐优先使用 Context API?

React并不推荐优先使用Context API的原因主要有以下几点:

  1. 实验性:Context API在React中仍然被视为实验性的特性,可能会在未来的版本中发生较大的变化,这会给应用的升级和维护带来麻烦。
  2. 复杂性:Context API的使用相对复杂,需要正确地创建Context对象、在Provider中提供数据、在Consumer或useContext钩子中消费数据,这增加了代码的复杂性和出错的可能性。
  3. 可靠性:Context的更新需要通过setState()触发,但这并不是完全可靠的。如果中间的子组件通过某些方法(如shouldComponentUpdate()返回false)阻止了更新,那么不能保证Context的更新能够传递到所有子组件。

因此,React建议优先使用props和state进行组件间的数据通信和状态管理,只有在必要时才考虑使用Context API。

React 的 state 是如何注入到组件中的?从 reducer 到组件经历了怎样的过程?

在React中,state通常是通过组件的props从父组件传递到子组件的。然而,在使用Redux等全局状态管理库时,state的注入过程会有所不同。以下是从reducer到组件的过程概述:

  1. 定义Reducer:Reducer是一个纯函数,它接收当前的state和action作为参数,并返回一个新的state。
  2. 创建Store:使用Redux提供的createStore函数,将reducer作为参数传递给该函数,从而创建一个store实例。这个store实例包含了应用的所有状态。
  3. Provider组件:在React应用的顶层,使用Redux的Provider组件来包裹整个应用。Provider组件接收store作为props,并将其提供给应用中的所有组件。
  4. 连接组件:使用react-redux库提供的connect函数或useSelector钩子,将组件与Redux store连接起来。这样,组件就可以通过访问store中的状态来更新自己的视图。
  5. 触发Action:当组件需要更新状态时,它会触发一个action。这个action被dispatch到store中,并由reducer处理以生成新的state。
  6. 更新视图:当store中的状态发生变化时,订阅了该状态的组件会接收到通知,并重新渲染以反映新的状态。

什么是 React 状态管理 MobX?它的应用场景有哪些?

MobX是一个流行的React状态管理库,它采用了一种称为“可观察数据”的概念来管理状态。在MobX中,你可以将状态定义为可观察的,并在状态发生变化时自动通知相关的组件进行更新。

MobX的应用场景包括但不限于:

  1. 大型应用:在大型应用中,状态管理变得尤为重要。MobX可以帮助你更好地组织和管理应用的状态,提高代码的可维护性和可扩展性。
  2. 复杂状态逻辑:当应用中的状态逻辑变得复杂时,使用MobX可以更容易地跟踪和管理状态的变化。
  3. 跨组件通信:在React中,跨组件通信是一个常见的问题。MobX提供了一种全局状态管理的解决方案,使得跨组件通信变得更加简单和直接。

Redux 底层如何实现属性传递?

Redux底层实现属性传递的过程主要依赖于其状态管理和数据流机制。以下是Redux实现属性传递的概述:

  1. 定义Action:Action是Redux中用于描述状态更新意图的对象。它通常包含一个type字段和一个可选的payload字段。
  2. 创建Reducer:Reducer是一个纯函数,它接收当前的state和action作为参数,并返回一个新的state。Reducer根据action的类型和payload来更新state。
  3. 创建Store:使用createStore函数创建Redux store,将reducer作为参数传递给该函数。Store是Redux中保存状态的地方,它提供了dispatch和getState等方法来更新和获取状态。
  4. Provider组件:在React应用中,使用Provider组件将store提供给应用中的所有组件。Provider组件通过context将store传递给其子组件。
  5. 连接组件:使用react-redux库提供的connect函数或useSelector钩子将组件与Redux store连接起来。这样,组件就可以通过访问store中的状态来更新自己的视图,并在必要时触发action来更新状态。

如何在 React 中实现双向绑定,并将其抽象成公共组件?

在React中实现双向绑定并将其抽象成公共组件的过程如下:

  1. 创建公共组件:首先,创建一个通用的输入组件(如InputField),它接受value和onChange两个属性。这些属性将用于实现双向绑定。
  2. 实现双向绑定:在输入组件内部,使用onChange事件处理器来更新父组件中的状态。这通常通过调用onChange回调函数并传递输入框的值来实现。
  3. 在父组件中使用公共组件:在父组件中,使用useState钩子来管理输入框的状态,并将这些状态作为props传递给InputField组件。同时,定义一个回调函数来处理状态更新。
  4. 抽象和复用:将InputField组件抽象为一个通用的双向绑定输入组件,并在需要的地方进行复用。这样,你可以在不同的表单场景中使用相同的组件,并简化表单处理逻辑。

以下是一个简单的示例代码:

// InputField.js
import React from 'react';const InputField = ({ label, value, onChange, type = 'text' }) => {const handleChange = (event) => {onChange(event.target.value);};return (<div><label>{label}<input type={type} value={value} onChange={handleChange} /></label></div>);
};export default InputField;// App.js
import React, { useState } from 'react';
import InputField from './InputField';const App = () => {const [name, setName] = useState('');const [age, setAge] = useState('');return (<div><h1>React双向绑定示例</h1><InputField label="Name: " value={name} onChange={setName} /><InputField label="Age: " value={age} onChange={setAge} type="number" /><div><p>输入的名字: {name}</p><p>输入的年龄: {age}</p></div></div>);
};export default App;

Redux 的 action 是什么?如何在 Redux 中定义 action?

Redux中的action是描述状态更新意图的对象。它们是单向数据流的核心,因为它们是唯一可以更新Redux store中状态的方法。

在Redux中定义action通常遵循以下步骤:

  1. 定义Action Type:为每个action定义一个唯一的类型字符串。这个类型用于在reducer中区分不同的action。
  2. 创建Action Creator:Action creator是一个函数,它返回一个action对象。这个函数可以接受一些参数来生成action的payload。
  3. 分发Action:在组件中,使用store的dispatch方法来分发action。这会触发reducer函数来更新store中的状态。

以下是一些定义Redux action的示例代码:

// 使用 createAction
const incrementCounter = createAction('INCREMENT_COUNTER');// 使用 createAsyncThunk
const fetchUserData = createAsyncThunk('FETCH_USER_DATA', async (userId) => {const response = await fetch(`/users/${userId}`);return response.json();
});// 使用 createSlice
const counterSlice = createSlice({name: 'counter',initialState: 0,reducers: {increment: (state) => state + 1,decrement: (state) => state - 1,},
});// 生成的action creators
const { increment, decrement } = counterSlice.actions;

在上面的示例中,我们使用了Redux Toolkit提供的createAction、createAsyncThunk和createSlice函数来定义action和相关的reducer逻辑。

什么是单一数据源?React 中怎么实现单一数据源?

单一数据源(Single Source of Truth)是指在一个系统中,所有的数据都来自一个可靠且唯一的来源。在React中,实现单一数据源通常意味着将应用的所有状态集中管理在一个地方(如Redux store),并通过组件来订阅和更新这些状态。

在React中实现单一数据源的方法包括但不限于:

  1. 使用Redux:Redux是一个流行的全局状态管理库,它允许你将应用的所有状态存储在一个单一的store中。组件可以通过订阅store中的状态来更新自己的视图,并在必要时触发action来更新状态。
  2. 使用MobX:MobX是另一个状态管理库,它采用可观察数据的概念来管理状态。在MobX中,你可以将状态定义为可观察的,并在状态发生变化时自动通知相关的组件进行更新。
  3. 使用Context API:虽然Context API通常用于跨组件通信和局部状态管理,但在某些情况下,你也可以使用它来创建全局状态管理的解决方案,从而实现单一数据源。然而,需要注意的是,React官方并不推荐优先使用Context API进行全局状态管理。

1. 除了实例属性,React 的 Context 还可以通过哪些方式直接获取?

React 的 Context API 提供了两种主要方式来直接获取和共享数据:

1.1 使用 useContext 钩子(函数组件)

useContext 是 React 16.8 引入的钩子,用于在函数组件中直接获取 Context 的值。

  • useContext 接受一个 Context 对象并返回该 Context 的当前值。
  • 函数组件使用 useContext 是访问 Context 的推荐方式。

示例:

import React, { createContext, useContext } from 'react';// 创建 Context
const ThemeContext = createContext('light');// 子组件
function ThemedComponent() {const theme = useContext(ThemeContext); // 直接使用 useContext 获取 Context 的值return <div>Current Theme: {theme}</div>;
}// 父组件
function App() {return (<ThemeContext.Provider value="dark"><ThemedComponent /></ThemeContext.Provider>);
}

解释

  • useContext(ThemeContext) 用于获取 ThemeContext 的当前值。
  • ThemeContext.Provider 提供的值 "dark" 被传递到 ThemedComponent 中。
1.2 使用 static contextType(类组件)

在类组件中,static contextType 是一种用于访问 Context 的方式。你可以通过类组件的 this.context 直接访问 Context 的值。

  • contextType 是一种静态属性,允许类组件声明它所要消费的 Context。
  • 一旦设置了 contextType,该类组件中的所有实例都可以通过 this.context 访问当前 Context 的值。

示例:

import React, { createContext } from 'react';// 创建 Context
const ThemeContext = createContext('light');// 类组件
class ThemedComponent extends React.Component {static contextType = ThemeContext; // 声明使用的 Context 类型render() {return <div>Current Theme: {this.context}</div>;}
}// 父组件
function App() {return (<ThemeContext.Provider value="dark"><ThemedComponent /></ThemeContext.Provider>);
}

解释

  • 通过 static contextType = ThemeContext;ThemedComponent 类组件就可以访问 ThemeContext 的当前值,通过 this.context 获取。
  • ThemeContext.Provider 提供的值 "dark" 被传递给子组件。
总结
  • 函数组件:使用 useContext 钩子获取 Context 的值。
  • 类组件:使用 static contextType 静态属性来声明要使用的 Context,并通过 this.context 获取值。

2. 什么是 Redux? 说说你对 Redux 的理解? 有哪些应用场景?

2.1 Redux 是什么?

Redux 是一个开源的 JavaScript 状态管理库,通常与 React 一起使用,用来管理全局应用的状态。它的设计理念是 单向数据流,并且通过一种严格的模式来控制状态的变更,使得整个应用的状态更具可预测性和可调试性。Redux 通过一个全局的 store 来集中管理应用的状态,状态只可以通过触发 action 并通过 reducer 来更新,确保了状态更新的可追溯性和一致性。

2.2 Redux 的核心概念
  1. Store(状态存储):Redux 的状态存储在 store 中,是整个应用的唯一数据源。通过 getState() 获取当前状态。

  2. Action(动作):Action 是一种描述状态变更的纯 JavaScript 对象。它通常包含 type 属性,表示动作的类型,有时还会有额外的数据(payload)。

    示例:

    const action = { type: 'INCREMENT', payload: 1 };
    
  3. Reducer(状态更新器):Reducer 是一个纯函数,接收 stateaction 作为参数,返回更新后的状态。Reducer 不应有副作用,不能直接修改状态,而是应返回新的状态对象。

    示例:

    const initialState = { count: 0 };function counterReducer(state = initialState, action) {switch (action.type) {case 'INCREMENT':return { ...state, count: state.count + action.payload };case 'DECREMENT':return { ...state, count: state.count - action.payload };default:return state;}
    }
    
  4. Dispatch(分发)dispatch 用于将 action 发送到 Redux store,触发状态的更新。

    示例:

    store.dispatch({ type: 'INCREMENT', payload: 1 });
    
  5. Middleware(中间件):Redux 中间件用于增强 dispatch 功能,支持异步操作和其他副作用(如 redux-thunkredux-saga)。

2.3 Redux 的工作流程
  1. Action 发起:用户操作(例如点击按钮)触发 action
  2. Action 分发dispatch(action) 发送 action 到 Redux store。
  3. Reducer 处理reducer 根据 action 更新状态,返回新的状态。
  4. 更新 Store:新状态更新到 store,组件根据状态变化重新渲染。
2.4 Redux 的工作原理

Redux 的核心思想是单向数据流

  • 状态只能通过 action 触发,reducer 更新状态。
  • 状态的变更是可追溯的,因为每次 action 的触发都能记录状态的变化。
  • dispatch(action) 触发时,状态的更新会沿着数据流动的路径(从组件到 store,再到 reducer)进行。
2.5 Redux 的应用场景

Redux 适用于以下场景:

  1. 多组件共享状态:当多个组件需要共享全局状态时,Redux 可以帮助集中管理这些状态,避免层层传递 props

    • 示例:登录用户信息、主题设置、购物车等。
  2. 复杂的状态更新逻辑:当应用的状态更新变得复杂,多个 action 对同一状态有影响时,Redux 通过 reducer 提供了清晰的更新流程,避免了混乱的状态管理。

    • 示例:表单状态的管理、动态更新的 UI 状态。
  3. 异步操作和副作用管理:Redux 本身不处理异步操作,但通过 redux-thunkredux-saga 等中间件,可以在 action 中处理异步请求,从而简化异步数据流的管理。

    • 示例:发起网络请求、处理用户登录、支付流程等。
  4. 需要时间旅行调试和日志:由于 Redux 状态的不可变性和 action 记录的特性,Redux 非常适合进行时间旅行调试和追踪历史状态。

    • 示例:使用 redux-devtools 进行调试和查看应用历史。
  5. 大型复杂应用:对于大型应用,Redux 提供了集中化的状态管理和良好的扩展性,使得应用能够更容易地进行维护和测试。

2.6 总结
  • Redux 是一个集中式的状态管理工具,适合处理大型、复杂的 React 应用,尤其是当多个组件需要共享和更新状态时。
  • 它的核心理念是单向数据流,通过 storeactionreducer 来确保状态更新的可预测性。
  • 使用 Redux 可以简化复杂应用的状态管理,尤其是在涉及异步操作、共享状态或调试时。

通过上述详细解释,基本涵盖了 Redux 的核心概念、应用场景及其工作原理,帮助你更好地理解 Redux 是如何在 React 中进行状态管理的。

1. React 的 Context API 能否取代 Redux? 为什么?

Context APIRedux 都是 React 中用于管理状态的工具,但它们适用于不同的场景。

Context API vs Redux
  • Context API

    • 是 React 提供的内置工具,适合于较为简单的状态管理,尤其是在多个组件之间共享数据时。
    • 它更适用于 小型应用局部状态共享,如主题、语言等。
    • 当 Context 用于管理复杂的状态(如大规模的数据流、异步请求等)时,性能和可维护性可能会下降,因为每次 Context 变化时,所有消费它的组件都会重新渲染。
  • Redux

    • 是一个更加 复杂和强大 的状态管理库,适用于大型应用或全局状态管理。
    • 它能够处理 复杂的异步操作多个数据流业务逻辑,并且可以进行更好的调试和状态跟踪。
    • Redux 通过 中间件(如 redux-thunkredux-saga)支持异步操作,具有更强的扩展性。

结论:Context API 可以在小型应用或局部状态管理中代替 Redux,但对于大型应用、复杂的状态更新或需要异步操作的场景,Redux 更为合适。


2. React 项目接入 Redux 的过程是什么? connect 的绑定过程是怎样的? connect 的原理是什么?

React 项目接入 Redux 的过程
  1. 安装 Redux 和 React-Redux

    npm install redux react-redux
    
  2. 创建 Redux store 和 reducer

    • 创建一个 reducer 来管理应用的状态。
    • 使用 createStore 创建 Redux store。
    import { createStore } from 'redux';const initialState = { count: 0 };function counterReducer(state = initialState, action) {switch (action.type) {case 'INCREMENT':return { count: state.count + 1 };case 'DECREMENT':return { count: state.count - 1 };default:return state;}
    }const store = createStore(counterReducer);
    
  3. 在应用中使用 Provider 组件
    Provider 将 Redux store 传递给应用中的所有组件。

    import { Provider } from 'react-redux';function App() {return (<Provider store={store}><Counter /></Provider>);
    }
    
  4. 在组件中连接 Redux
    使用 connect 来连接 React 组件和 Redux store,从而获取 state 和 dispatch action。

connect 的绑定过程
  • connect 是一个高阶组件,它通过将 statedispatch 作为 props 传递给 React 组件,来实现 Redux 状态的绑定。
  • connect 需要两个参数:
    • mapStateToProps: 选择 store 中的 state 并将其映射为组件的 props。
    • mapDispatchToProps: 将 action 创建函数映射为组件的 props。

示例:

import React from 'react';
import { connect } from 'react-redux';// 映射 state 到组件的 props
const mapStateToProps = (state) => ({count: state.count,
});// 映射 dispatch 到组件的 props
const mapDispatchToProps = (dispatch) => ({increment: () => dispatch({ type: 'INCREMENT' }),decrement: () => dispatch({ type: 'DECREMENT' }),
});function Counter({ count, increment, decrement }) {return (<div><p>Count: {count}</p><button onClick={increment}>Increment</button><button onClick={decrement}>Decrement</button></div>);
}// 使用 connect 连接 Redux store
export default connect(mapStateToProps, mapDispatchToProps)(Counter);
connect 的原理

connect 是一个高阶组件,它会:

  • 自动订阅 Redux store:组件会自动重新渲染当 Redux store 中的数据发生变化时。
  • 传递数据和方法:它将 Redux store 中的 statedispatch 方法通过 mapStateToPropsmapDispatchToProps 映射为组件的 props,从而让组件能够访问并更新 Redux store。

3. Redux 和 Vuex 状态管理有什么区别? 它们的共同思想是什么?

区别
  1. 框架依赖

    • Redux 是一个框架无关的状态管理库,适用于任何 JavaScript 应用,通常与 React 一起使用。
    • Vuex 是 Vue.js 官方的状态管理库,专为 Vue 应用设计。
  2. 状态变更的方式

    • Redux 依赖 reducer 来处理状态变更,action 是必须通过 dispatch 触发的。
    • Vuex 使用 mutations 来修改状态,actions 用于异步操作,getters 用于计算派生状态。
  3. 异步操作

    • Redux 通常使用中间件(如 redux-thunkredux-saga)来处理异步操作。
    • Vuex 使用 actions 来处理异步操作,异步操作最终会提交 mutations
  4. 易用性

    • Redux 设计较为复杂,适合处理大型应用,提供更精细的状态管理。
    • Vuex 更简洁且与 Vue 框架紧密集成,适合用于中小型 Vue 应用。
共同思想
  • 单一数据源:应用的状态被集中存储在一个全局的 store 中,所有组件通过 store 来访问和更新状态。
  • 不可变性:状态在更新时不会直接修改原有数据,而是返回一个新的状态对象。
  • 单向数据流:数据的流动遵循从组件到 store,再从 store 到组件的单向流动。

4. redux-saga 和 Mobx 有什么区别?

redux-saga
  • 功能redux-saga 是一个中间件,用于管理副作用,特别是处理复杂的异步逻辑、并发请求和取消任务。
  • 工作方式:基于 Generator 函数,通过 yield 控制流来处理异步任务。
  • 适用场景:适用于需要大量复杂异步操作的场景,像网络请求、文件上传等。
MobX
  • 功能:MobX 是一个响应式状态管理库,通过观察者模式实现自动的状态更新。
  • 工作方式:使用 observable(可观察对象)和 reaction(反应式)来自动跟踪数据依赖关系,状态变化时自动更新组件。
  • 适用场景:适用于中小型应用或者对性能要求较高的场景,尤其是在管理组件间的状态时非常方便。
区别
  • Redux-saga 强调函数式编程和复杂的副作用处理,而 MobX 更加声明式和简洁,关注自动化的响应式状态更新。
  • redux-saga 依赖于 Redux,而 MobX 可以独立使用,且易于与 React 直接结合。

5. 非父子组件如何进行通信?

在 React 中,非父子组件之间的通信通常有以下几种方式:

  1. 使用 Context API:在 Context 提供者组件中,提供共享数据,任意后代组件都可以访问该数据。
  2. 使用全局状态管理库(如 Redux 或 MobX):通过全局状态管理器实现跨组件的数据共享和更新。
  3. Event Emitters:可以通过事件驱动的方式,在应用中创建一个事件中心(或使用第三方库,如 EventEmitter),组件通过监听或触发事件来进行通信。

6. React 和 Redux 中,哪些功能使用了设计模式?

  • Redux

    • 观察者模式:Redux 的订阅机制使用了观察者模式。组件通过 connect 订阅 store 的更新,组件在 state 变化时会自动重新渲染。
    • 单例模式:Redux 的 store 是一个单例对象,整个应用只有一个 store 实例来管理状态。
  • React

    • 组合模式:React 的组件架构本身就是组合模式。通过嵌套组件和传递 props,可以组合成更复杂的 UI 结构。
    • 高阶组件模式(HOC):connect 就是一个高阶组件,用于将 Redux 的功能(如 statedispatch)注入到组件中。

7. **Redux 数据流

的流程是怎样的?**

Redux 的数据流遵循 单向数据流

  1. Action 触发:用户操作或系统事件触发 action(一个 JavaScript 对象),表示状态变更。
  2. Dispatchdispatch(action) 被调用,Redux 将该 action 传递给 reducer。
  3. Reducerreducer 函数根据 action 类型更新状态,并返回新的状态。
  4. Store 更新store 接收到新的状态并更新。
  5. 组件更新:React 组件通过 connectuseSelector 订阅 store 的变化,状态更新时组件会自动重新渲染。

8. redux-saga 和 redux-thunk 有什么本质区别?

  • redux-thunk

    • redux-thunk 是 Redux 的中间件,允许在 action 中返回一个函数,函数接受 dispatchgetState 作为参数,通常用于异步请求。
    • 它的工作方式比较简单,直接在 action 中进行异步操作。
  • redux-saga

    • redux-saga 基于 Generator 函数,通过 yield 控制异步逻辑的流程,可以处理更加复杂的异步操作(如并发请求、任务取消、错误处理等)。
    • 它的工作方式较为复杂,但提供了更强大的副作用处理能力。

9. Redux 中间件接受几个参数? 柯里化函数的两端参数具体是什么?

Redux 中间件通常接收 3 个参数

  1. store:Redux store,提供 dispatchgetState 方法。
  2. next:一个函数,用于将 action 传递给下一个中间件。
  3. action:当前被分发的 action 对象。

10. 如果 React 的 Consumer 组件在上下文树中找不到 Provider,如何处理?

如果 React 的 Consumer 组件在上下文树中找不到 Provider,它会使用 Context默认值createContext() 时定义的默认值会作为 Consumer 的值。


11. React 的状态管理器解决了什么问题? 何时使用状态管理器?

问题

  • 状态共享问题:在多个组件之间传递和共享数据,特别是在深层嵌套组件中。
  • 状态更新问题:在需要进行大量状态更新时,如何保持状态更新的可预测性。
  • 异步操作管理:如何在状态更新过程中处理异步操作。

何时使用

  • 当多个组件共享状态时。
  • 当应用状态变得复杂或需要进行大量的状态更新时。
  • 当需要处理异步请求和副作用时。

希望以上回答能帮助你全面理解这些问题。

Redux 的三个原则是什么?

Redux 的三个原则是:

  1. 单一事实来源(Single Source of Truth):整个应用的状态被存储在一个单一的中央存储库中,称为 store。这确保了应用状态的一致性和可预测性。
  2. 状态只读(State is Read-Only):应用状态不能直接被修改。任何状态更新都必须通过触发一个 action 来实现,而这个 action 会被一个 reducer 函数处理,以产生一个新的状态。
  3. 纯函数用于改变状态(Changes are Made with Pure Functions):要指定状态树如何因 action 而改变,你需要编写纯函数来执行这种改变。这些纯函数被称为 reducers。

React 中,父子组件如何进行通信?

在 React 中,父子组件通信是最基本的通信方式。主要有两种方式:

  1. Props:父组件通过将属性(props)传递给子组件来共享数据。
function ParentComponent() {const message = "Hello from parent";return <ChildComponent message={message} />;
}function ChildComponent(props) {return <div>{props.message}</div>;
}
  1. 回调函数:子组件可以通过调用父组件传递给它的回调函数来传递数据。
function ParentComponent() {const handleMessage = (childMessage) => {console.log(childMessage);};return <ChildComponent onMessage={handleMessage} />;
}function ChildComponent(props) {const message = "Hello from child";return <button onClick={() => props.onMessage(message)}>Send Message</button>;
}

React 中,兄弟组件如何进行通信?

兄弟组件(即没有直接父子关系的组件)之间的通信通常通过它们的父组件来做中转。

  1. 父组件在子组件 A 里绑定一个事件监听函数,子组件 A 通过该函数入参把想传递的数据交给父组件。
  2. 父组件拿到数据后,通过 setState 更改父组件当前的 state 数据。
  3. 父组件再把这个数据通过 props 的方式传递给子组件 B。

这样就实现了兄弟组件通信。

Redux 的 reducer 是什么?它有什么作用?

在 Redux 中,reducer 是一个纯函数,用于处理应用的状态变化。它接收一个旧的状态和一个描述状态变化的动作对象(action),并返回一个新的状态。

reducer 的作用是根据 action 的类型来判断需要对状态进行何种变化,并返回一个新的状态对象。这个新的状态对象将被保存在 Redux 的 store 中,供应用使用。

在 React 项目中,你会怎么实现异步能力?

在 React 项目中,可以通过多种方式实现异步能力,例如:

  1. 使用异步函数和 async/await:可以定义一个异步函数,并在其中使用 await 关键字来等待异步操作的结果。
  2. 使用 Promise:可以使用 Promise 来封装异步操作,并通过 thencatch 方法来处理异步操作的结果和错误。
  3. 使用 Redux Thunk 或 Redux Saga:这些是 Redux 的中间件,用于处理异步 action。它们允许你在 action 被分发后执行异步操作,并在操作完成后分发新的 action 来更新状态。

什么是 React 的 Redux?它主要解决了什么问题?它有哪些应用场景?

React 的 Redux

Redux 是一个状态管理库,它可以与 React 一起使用,为应用提供一个集中式的状态存储和管理解决方案。

主要解决的问题

Redux 主要解决了 React 应用中状态管理的问题。随着应用规模的扩大,组件之间的状态共享和更新变得复杂且难以维护。Redux 提供了一个清晰的状态管理方案,使得状态的变化可预测、可调试和可扩展。

应用场景

  1. 大型应用:对于具有复杂状态管理的大型应用,Redux 提供了强大的工具来组织和维护状态。
  2. 跨组件通信:当多个组件需要共享状态时,Redux 可以作为一个中心化的状态存储来简化跨组件通信。
  3. 状态一致性:Redux 确保了应用状态的一致性和可预测性,使得调试和测试变得更加容易。

React 中,非兄弟组件如何进行通信?

在 React 中,非兄弟组件(即没有直接关系的组件)之间的通信通常通过以下几种方式实现:

  1. Context API:React 提供了 Context API 来跨组件层级传递数据,而不需要通过每一层的 props 传递。
  2. Redux:如前所述,Redux 是一个状态管理库,可以用来管理应用的状态,并通过 actions 和 reducers 来跨组件共享状态。
  3. 全局状态管理工具:除了 Redux,还有其他全局状态管理工具如 MobX 等,也可以用于跨组件通信。

Redux 由哪些组件构成?

Redux 主要由以下几个组件构成:

  1. Store:全局唯一的数据源,它是只读的。
  2. State:Store 中的数据,表示应用的状态。
  3. Action:一个描述状态更新意图的对象,被分发到 store 中。
  4. Reducer:一个纯函数,接收旧的状态和 action,并返回一个新的状态。

React 的 Context API 有哪些主要属性?

React 的 Context API 有以下主要属性:

  1. React.createContext:用于创建一个上下文对象,该对象包含两个属性:Provider 和 Consumer。
  2. Provider:一个 React 组件,用于包裹其他组件,并通过 value 属性提供需要传递的数据。
  3. Consumer:一个 React 组件,用于消费由 Provider 提供的数据。在函数组件中,可以使用 useContext 钩子来替代 Consumer。

通过这些属性,Context API 允许跨组件层级传递数据,而不需要通过每一层的 props 传递。

1. Redux 中异步 action 和同步 action 有什么区别?

同步 action
  • 定义:同步 action 是指直接描述如何更新状态的 JavaScript 对象。这些 action 立即执行,并且不会涉及到任何延迟的操作。
  • 行为:同步 action 是直接通过 dispatch 发送到 reducer,reducer 会处理这些 action 并更新应用的状态。
  • 示例
    const incrementAction = { type: 'INCREMENT' };
    store.dispatch(incrementAction);
    
异步 action
  • 定义:异步 action 涉及到延迟操作,如网络请求、定时器、文件读取等。由于 JavaScript 是单线程的,异步操作通常需要一种机制来处理这些延迟操作。
  • 行为:在 Redux 中,异步 action 通常使用中间件(如 redux-thunkredux-saga)来处理。中间件使得可以在 action 中返回一个函数或 Promise,这些异步操作会在后端执行,然后再派发一个同步的 action 来更新状态。
  • 示例(使用 redux-thunk)
    const fetchUserData = () => {return (dispatch) => {dispatch({ type: 'FETCH_USER_REQUEST' });fetch('/api/user').then(response => response.json()).then(data => dispatch({ type: 'FETCH_USER_SUCCESS', payload: data })).catch(error => dispatch({ type: 'FETCH_USER_FAILURE', error }));};
    };
    
区别总结
  • 同步 action:立即执行,直接更新 state。
  • 异步 action:延迟执行,通常与网络请求、定时操作等相关,需要通过中间件来管理。

2. 什么是 React 受控组件和非受控组件? 它们有什么区别?

受控组件
  • 定义:受控组件是指 React 中的表单元素(如 <input><textarea> 等),其值由 React 组件的 state 控制。用户的输入会通过 onChange 事件处理程序更新 React 组件的状态。

  • 特点

    • React 组件完全控制表单元素的状态。
    • 每次用户输入时,都会更新组件的 state。
  • 示例

    import React, { useState } from 'react';function ControlledComponent() {const [value, setValue] = useState('');const handleChange = (e) => {setValue(e.target.value);};return (<input type="text" value={value} onChange={handleChange} />);
    }
    
非受控组件
  • 定义:非受控组件的值不由 React 组件的 state 控制,而是由 DOM 本身管理。React 通过 ref 来直接访问 DOM 元素,获取其当前值。

  • 特点

    • React 不控制表单元素的状态,表单元素的状态由 DOM 自行管理。
    • 在提交表单或获取数据时,可以通过 ref 获取值。
  • 示例

    import React, { useRef } from 'react';function UncontrolledComponent() {const inputRef = useRef();const handleSubmit = (e) => {e.preventDefault();alert(`Input value: ${inputRef.current.value}`);};return (<form onSubmit={handleSubmit}><input type="text" ref={inputRef} /><button type="submit">Submit</button></form>);
    }
    
区别总结
  • 受控组件:表单元素的状态由 React state 管理,数据流由 React 完全控制。
  • 非受控组件:表单元素的状态由 DOM 自己管理,React 通过 ref 来访问和获取表单数据。

3. Redux 的 thunk 有什么作用?

redux-thunk 是 Redux 的一个中间件,主要用于处理异步操作。它允许在 action 创建函数中返回一个函数,而不是普通的 action 对象。这个返回的函数接收 dispatchgetState 作为参数,允许你在函数内部进行异步操作(如发起 API 请求),并在异步操作完成后 dispatch 一个同步 action 来更新状态。

作用
  • 处理异步操作:可以让你在 action 中处理异步请求、延时操作等,直到异步操作完成后再派发一个同步 action。
  • 支持延迟执行:允许你在 dispatch 之前执行异步操作或逻辑。

示例

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';// Redux store 和 reducer
const reducer = (state = { count: 0 }, action) => {switch (action.type) {case 'INCREMENT':return { count: state.count + 1 };default:return state;}
};const store = createStore(reducer, applyMiddleware(thunk));// 异步 action
const incrementAsync = () => {return (dispatch) => {setTimeout(() => {dispatch({ type: 'INCREMENT' });}, 1000);};
};// Dispatch 异步 action
store.dispatch(incrementAsync());

4. 在 React 项目中如何使用 Redux? 项目结构如何划分?

1. 安装 Redux 和 React-Redux
npm install redux react-redux
2. 创建 Redux store 和 reducer
// store.js
import { createStore } from 'redux';const initialState = { count: 0 };const reducer = (state = initialState, action) => {switch (action.type) {case 'INCREMENT':return { count: state.count + 1 };case 'DECREMENT':return { count: state.count - 1 };default:return state;}
};const store = createStore(reducer);export default store;
3. 使用 Provider 包裹应用组件
// App.js
import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import Counter from './Counter';function App() {return (<Provider store={store}><Counter /></Provider>);
}export default App;
4. 在组件中使用 connect 连接 Redux store
// Counter.js
import React from 'react';
import { connect } from 'react-redux';const Counter = ({ count, dispatch }) => {return (<div><p>Count: {count}</p><button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button><button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button></div>);
};const mapStateToProps = (state) => ({count: state.count,
});export default connect(mapStateToProps)(Counter);
项目结构
/src/actions          // 存放 Redux 的 action 文件/components       // React 组件/reducers         // 存放 Redux 的 reducer 文件/store            // 创建 store 的地方App.js            // 主应用组件index.js          // 入口文件

5. 什么是 React 的 Consumer 组件? 它有什么作用?

Consumer 组件是 React Context API 的一部分,用于在组件树中访问 Context 的值。Consumer 必须被 Provider 包裹,才能访问到由 Provider 提供的值。

  • 作用Consumer 组件通过一个函数作为子组件,接收一个 value(来自 Context.Provider)作为参数,并返回一个 React 元素。每当 value 发生变化时,Consumer 会重新渲染。

示例

import React, { createContext } from 'react';const MyContext = createContext('default value');function App() {return (<MyContext.Provider value="Hello, World!"><MyComponent /></MyContext.Provider>);
}function MyComponent() {return (<MyContext.Consumer>{(value) => <div>{value}</div>}</MyContext.Consumer>);
}

6. 为什么要使用 Vuex 或者 Redux 状态管理? 能够解决什么问题?

问题
  • 组件之间状态共享:当多个组件需要共享相同的状态时,通过 props 传递数据会变得非常麻烦,尤其是嵌套组件多时。
  • 复杂状态更新:当应用状态变得复杂,涉及多个组件和不同的数据流时,管理状态变得困难。
  • 跨组件的同步问题:当需要异步请求和跨组件更新时,传统的 React 状态管理方法无法提供高效的解决方案。
解决方案
  • 全局状态管理:Vuex 和 Redux 都提供了全局状态存储,允许多个组件从一个中心化的 store 获取和更新状态。
  • 清晰的数据流:通过 actionmutationreducer 来管理状态的更新,确保数据流是可预测的。
  • 支持异步操作:通过中间件(如 redux-thunkvuex-actions)支持异步操作,使得异步任务能够被很好地管理和控制。

7. Redux 和 Vuex 有什么区别? 它们的共同设计思想是什么?

区别
  • 框架

    • Redux 是一个独立的库,专为 React 设计,也可以与其他框架或库一起使用。
    • Vuex 是 Vue.js 的官方状态管理库,专为 Vue.js 设计。
  • 异步操作

    • Redux 通过中间件(如 redux-thunkredux-saga)处理异步操作。
    • Vuex 使用 actions 来处理异步操作,并通过 mutations 来修改状态。
共同设计思想
  • 单一数据源:应用的所有状态都集中存储在一个单一的 store 中,所有组件都通过该 store 访问和更新状态。
  • 单向数据流:从组件通过 dispatch 发送 action,然后通过 reducermutation 更新 state,最后更新的状态会自动反映到组件中。
  • 不可变状态:状态是不可变的,每次修改都返回一个新的状态对象。

希望这些回答能帮助你更好地理解 React 和 Redux 的相关概念以及它们之间的区别。


http://www.ppmy.cn/ops/142978.html

相关文章

51c嵌入式~单片机~合集3

我自己的原文哦~ https://blog.51cto.com/whaosoft/12362395 一、STM32代码远程升级之IAP编程 IAP是什么 有时项目上需要远程升级单片机程序&#xff0c;此时需要接触到IAP编程。 IAP即为In Application Programming&#xff0c;解释为在应用中编程&#xff0c;用户自己的…

Linux 设备树

学习设备树之前你需要知道什么&#xff1f; 因为设备树描述了整个芯片和开发板等所有硬件信息内容&#xff0c;所以他的信息量是非常庞大的&#xff0c;RK的linux的设备树算下来大概就有九千多行&#xff0c;大家不要被这个数字给吓到&#xff0c;这些内容都是原厂工程师写的&a…

鸿蒙开发-ArkTS 创建自定义组件

在 ArkTS 中创建自定义组件是一个相对简单但功能强大的过程。以下是如何在 ArkTS 中创建和使用自定义组件的详细步骤&#xff1a; 一、定义自定义组件 使用Component注解&#xff1a;为了注册一个组件&#xff0c;使其能够在其他文件中被引用&#xff0c;你需要使用Component…

牛客周赛72:B:JAVA

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 小红定义一个字符串是好串&#xff0c;当且仅当该字符串任意一对相邻字符都不同。 现在小红拿到了一个01串&#xff0c;请你帮小红求出有多少个长度不小于2的连续子串是好串。 输…

运行 Mongodb Server

如何使用 mongod 命令通过配置文件启动 MongoDB Server 适用于通过 Homebrew 安装的 MongoDB Server 如果您的 MongoDB Server 是通过 Homebrew 安装的&#xff0c;则安装过程中会自动创建必要的文件夹和配置文件&#xff08;如 mongod.conf&#xff09;。您可以直接使用以下…

MVC前后端交互案例--留言板

API-约定前后端交互接⼝ 约定 " 前后端交互接⼝ " 是进⾏ Web 开发中的关键环节. 接⼝⼜叫 API&#xff08;Application Programming Interface), 我们⼀般讲到 接⼝或者 API&#xff0c; 指的都是同⼀个东西。 是指应⽤程序对外提供的服务的描述, ⽤于 交换信息和执…

登陆harbor发现证书是错误的, 那么如何更新harbor的证书呢

Error response from daemon: Get "https://172.16.21.35/v2/": tls: failed to verify certificate: x509: certificate is valid for 127.0.0.1, ::1, 172.16.21.30, not 172.16.21.35 版本 v2.10.1-b7b88476 不需要从头看, 直接看最下面的成功的证书创建 这里面首…

23.DDD与微服务

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 文章目录 DDD与微服务的关系1. DDD可以用微服务实现&#xff0c;也可以不用微服务实现2. DDD是微服务拆分的必须参考项之一3. 微服务架构…