// ----------useState-----------------
let state = [];
// 对应值
let setters = [];
// 对应设置状态值方法
let stateIndex = 0;
function createSetter(index) {
return function (newState) {
state[index] = newState;
// 状态更改后重新渲染视图
render();
};
}function useState(initialState) {
// state = state ? state : initialState;
state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialState;
// function setState(newState) {
//console.log(newState);
//state = newState;
//// 状态更改后重新渲染视图
//render();
// }
setters.push(createSetter(stateIndex));
let value = https://www.it610.com/article/state[stateIndex];
let setter = setters[stateIndex];
stateIndex++;
return [value, setter];
}// --------------useEffect-----------------
// 上一次的依赖值
let prevDepsAry = [];
// 结果应该为一个二位数组
let effectIndex = 0;
function useEffect(callback, depsAry) {
// 判断callback是不是函数
if (Object.prototype.toString.call(callback) !=="[object Function]") {
throw new Error("useEffect函数的第一个参数必须是函数");
}
// 判断depsAry有没有被传递
if (typeof depsAry === "undefined") {
// 没有传递
callback();
} else {
// 判断depsAry是不是数组
if (Object.prototype.toString.call(depsAry) !== "[object Array]") {
throw new Error("useEffect函数的第二个参数必须是数组");
}
// 获取上一次的状态值
let prevDeps = prevDepsAry[effectIndex];
// 将当前的依赖值和上一次的依赖值做对比 如果有变化 调用callback
let hasChange = prevDeps
? depsAry.every((dep, index) => dep === prevDeps[index]) === false
: true;
// 判断值是否有变化
if (hasChange) {
callback();
}
// 同步依赖值
prevDepsAry[effectIndex] = depsAry;
effectIndex++;
}
}// -------------useReduce-------------
function useReducer(reducer, initialState) {
const [state, setState] = useState(initialState);
function dispatch(action) {
const newState = reducer(state, action);
setState(newState);
}
return [state, dispatch];
}function reducer(state, action) {
switch (action.type) {
case "increment":
return state + 1;
case "decrement":
return state - 1;
default:
return state;
}
}
const [count, dispatch] = useReducer(reducer, 0);
function render() {
stateIndex = 0;
effectIndex = 0;
ReactDOM.render(, document.getElementById("root"));
}
【useState,useEffect,useReduce手写实现】类似于antd的一些组件库的组件,经常需要绑定一些value值和onChange事件。可以封装一个通用方法
function useUpdateInput(initvalue) {
const [value, setValue] = useState(initvalue);
return {
value,
onChange: (e) => setValue(e.target.value),
};
}
const username = useUpdateInput("");
Lazy使用
const LazyComponent = React.lazy(() => import('./test.js'))export default function Index(){
return
}function Test(){
return hello world
}
const LazyComponent =React.lazy(()=> new Promise((resolve)=>{
setTimeout(()=>{
resolve({
default: ()=>
})
},2000)
}))
react中lazy实现
function lazy(ctor){
return {
$$typeof: REACT_LAZY_TYPE,
_payload:{
_status: -1,//初始化状态
_result: ctor,
},
_init:function(payload){
if(payload._status===-1){ /* 第一次执行会走这里*/
const ctor = payload._result;
const thenable = ctor();
payload._status = Pending;
payload._result = thenable;
thenable.then((moduleObject)=>{
const defaultExport = moduleObject.default;
resolved._status = Resolved;
// 1 成功状态
resolved._result = defaultExport;
/* defaultExport 为我们动态加载的组件本身*/
})
}
if(payload._status === Resolved){ // 成功状态
return payload._result;
}
else {//第一次会抛出Promise异常给Suspense
throw payload._result;
}
}
}
}
Suspense让数据获取库与 React 紧密整合。如果一个数据请求库实现了对 Suspense 的支持,那么,在 React 中使用 Suspense 将会是自然不过的事。
Suspense能够自由的展现,请求中的加载效果。能让视图加载有更主动的控制权。
Suspense能够让请求数据到渲染更流畅灵活,我们不用在componentDidMount请求数据,再次触发render,一切交给Suspense解决,一气呵成。