// ----------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 = 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(<App />, document.getElementById("root"));
}
相似于 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 <Suspense fallback={<div>loading...</div>} >
<LazyComponent />
</Suspense>
}
function Test(){return <div className="demo" >hello world</div>}
const LazyComponent = React.lazy(()=> new Promise((resolve)=>{setTimeout(()=>{
resolve({default: ()=> <Test />
})
},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 解决,零打碎敲。