React全栈开发
一、Redux
使用Redux相对于context api的优势:
- 单一数据源:使用全局唯一的状态树来存储应用程序的状态,使得状态管理更加集中和一致。使用Context API时,状态可能会分散在多个上下文中。
- 分离关注点:通过actions和reducers将状态更新逻辑与组件逻辑分离。使用Context API时,状态更新逻辑可能会与组件逻辑混在一起,导致组件和逻辑之间的耦合度增加。
// actions.js export const fetchDataRequest = () => ({ type: 'FETCH_DATA_REQUEST' }); export const fetchDataSuccess = data => ({ type: 'FETCH_DATA_SUCCESS', payload: data }); export const fetchData = () => async dispatch => { dispatch(fetchDataRequest()); try { const response = await fetch('https://jsonplaceholder.typicode.com/todos/1'); const data = await response.json(); dispatch(fetchDataSuccess(data)); } catch (error) { console.error(error); } }; // reducer.js const initialState = { loading: false, data: null }; export const dataReducer = (state = initialState, action) => { switch (action.type) { case 'FETCH_DATA_REQUEST': return { ...state, loading: true }; case 'FETCH_DATA_SUCCESS': return { ...state, loading: false, data: action.payload }; default: return state; } }; // App.js 和其他 Redux 相关代码保持不变 // DataComponent.js
// 组件逻辑中,完全跟状态更新逻辑(异步获取数据等)解耦 import React, { useEffect } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { fetchData } from './actions'; const DataComponent = () => { const { data, loading } = useSelector(state => state); const dispatch = useDispatch(); useEffect(() => { dispatch(fetchData()); }, [dispatch]); return ( <div> {loading ? ( <p>Loading...</p> ) : ( <p>Data: {data && JSON.stringify(data)}</p> )} </div> ); }; export default DataComponent;
二、Nextjs
分为AppRouter和PageRouter两种模式,其中AppRouter是更新、更为推荐的模式
1、SSR
AppRouter中,默认组件就是Server Component,对应访问请求就是SSR模式; 通过设置`client component`的指令,标记组件是Client Component,对应页面访问就是CSR模式。
PageRouter中,如果页面组件文件有实现类似getServerProps、getIniialProp等方法,就是SSR模式; 反之,就是CSR模式。
2、缓存
AppRouter模式,Next.js里面自动扩展了fetch方法。 会实现Request模式、Data模式等缓存方案。
3、部署
- 静态资源: build后静态资源在/public/static目录,推送到CDN; 然后在next.config.js里面配置pubilcPath为CDN地址
- 服务: 部署执行 next start就可以; 或者配置docker file
4、常见坑
- SSR页跳转另外SSR页,原页面会因为store更新而多余render
next-redux-wrapper
在接收到SSP
的返回后,会默认触发Hydrate Action
,从而引起不同页面的Reducer
监听到 Hydrate Action
触发,然后进行Store
的更新;而此时Store只有新SSR页的store数据,原SSR页的store数据没有了,所以导致render。
https://segmentfault.com/a/1190000043700244
三、Fiber原理
1、Fiber是什么?
Fiber是一种新的数据结构,表示一个元素节点,包含了type、props、key、parent、sibling、child等属性。 用一种双向链表结构取代以前的树节点结构。
2、为什么需要Fiber?
因为React每次状态更新,就需要重新构建整个React组件树的Virtual Dom; 这就带来了新旧Virtual Dom对比的CPU压力,从而会占据JS thread运行时间,导致卡顿情况。
引入Fiber:
- 把1个大rerender过程划分到多个桢里面,虽然整体耗时不变,但用户体感上会更流畅
3、 如何实现Fiber?
- Fiber的双向链表结构,保证只要记录上一次中断的Fiber节点,就可以继续往后遍历(通过parent、sibling、child等指针)执行
- 类似借助浏览器的requestIdleCallback,再每帧空余时间执行(实际上是React为了浏览器兼容,自己实现了Polyfill)
const workLoop = (deadLine) => { let shouldYield = false;// 是否该让出线程 while(!shouldYield){ console.log('working') // 遍历节点等工作。。。 shouldYield = deadLine.timeRemaining()<1; // deadLine.timeRemaining是浏览器API,用于返回当前桢还剩余时间 } requestIdleCallback(workLoop) } requestIdleCallback(workLoop);
4、Diff算法