繁体   English   中英

如何用 vanilla JS 复制 useState

[英]How to replicate useState with vanilla JS

Vanilla JS 中的代码实现是什么,它允许我们声明和更新 state,就像 useState 在 React 中那样:

const [x, setX] = useState(12);
setX(14);
console.log(x); // 14

这个问题在 JS 中严格变得更好。 天真地认为 go 是有意义的:

// Solution 1

function update(value, newValue) {
    value = newValue;
    return value;
}

function state(value) {
    return [ value, update ];
}

let [value, setValue] = state(12)
value = setValue(value, 14)
console.log(value); // 14


// Solution 2

class State {
    constructor(value) {
        this.value = value;
    }
    
    update(newValue) {
        this.value = newValue;
    }
}

const x = new State(12);
x.update(14);
console.log(x.value); // 14

但我不明白数组 [x, setX] 有一个回调 (setX),当用 const 声明时会影响 x? 我希望这是有道理的。

您缺少一些非常重要的东西 - 所有的反应钩子都使用“支持”它们的东西,这允许您在没有实例时提供有效的实例变量,您只有一个函数。

React 中的这个东西被称为纤程,它有效地代表了 React 组件的生命周期——它与函数本身无关,本身,它与组件相关,react 正在渲染(和重新渲染)。 这就是为什么你可以有一个函数式组件声明,多次渲染同一个函数,每个都能够维护自己的状态——状态不是函数的一部分,状态是 React 纤维的一部分。

但我不明白数组 [x, setX] 如何有一个回调(setX),当用 const 声明时会影响 x?

当您调用setX ,您并不是简单地改变 x 的值,您正在做的是告诉 React 使用 x 的新值重新渲染组件(光纤)。

编辑:

一个非常简单的例子,其中函数本身被用作状态的支持实例(在 React 中不是这种情况)可能看起来像这样:

 // this line is example only so we can access the stateSetter external to the function let stateSetter; const states = new Map(); const useState = (value,context) => { const dispatch = v => { const currentState = states.get(context.callee); currentState[0] = typeof v === 'function' ? v(currentState[0]) : v // we re-call the function with the same arguments it was originally called with - "re-rendering it" of sorts... context.callee.call(context); } const current = states.get(context.callee) || [value,dispatch]; states.set(context.callee,current); return current; } const MyFunction = function(value) { const [state,setState] = useState(value, arguments) stateSetter = setState; console.log('current value of state is: ',state) } MyFunction(10); MyFunction(20); // state hasn't changed stateSetter('new state'); // state has been updated!

我也想学习如何做到这一点。 我在这里找到了如何做 我重构了代码以使用箭头函数,这会使代码片段更难阅读和理解。 如果是这种情况,请前往上面链接中共享的资源。

这是实现:

const useState = (defaultValue) => {
  // 👆 We create a function useState with a default value
  let value = defaultValue;
  // 👆 We create a local variable value = defaultValue
  const getValue = () => value
  // 👇 We create a function to set the value with parameter newValue
  const setValue = newValue => value = newValue // 👈 We change the value for newValue
  return [getValue, setValue]; // 👈 We return an array with the value and the function
}

const [counter, setCounter] = useState(0);
// 👆 We destructure the array as a return of the useState function into two value

console.log(counter()); // 👈 returns 0 which it's the value of counter()

我添加了注释以便于理解。 这是没有注释的实现:

const useState = (defaultValue) => {
  let value = defaultValue;
  const getValue = () => value
  const setValue = newValue => value = newValue
  return [getValue, setValue];
}

const [counter, setCounter] = useState(0);

console.log(counter());

为了更好地阅读和理解,我使用常规函数包含了该片段:

function useState(defaultValue) {
  let value = defaultValue

  function getValue() {
    return value
  }

  function setValue(newValue) {
    value = newValue
  }

  return [getValue, setValue];
}

const [counter, setCounter] = useState(0);

使用构造函数模拟useState()简单解决方案。 这可能不是最好的解决方案,因为构造函数每次都返回一个函数的副本,但却解决了有问题的问题。

function Hook(){
  return function (initialState){
    this.state = initialState;
    return [
      this.state,
      function(newState){
        this.state = newState;
      }
    ];
  }
}
const useState = new Hook();

现在,解构useState() ,它是Hook()一个实例

const [state, setState] = useState(0);
console.log(state); // 0
setState({x:20});
console.log(state); // { x: 20 }
setState({x:30});
console.log(state); // { x: 30 }

1.- 解构 function 返回的值。

  • 我们应用它来解构 function 中返回的数组的两个值。

  • 第一个值将返回变量的当前数据,第二个值将更改 function 以表示该值。

 // Main function useState (similar to react Hook) function useState(value){ // Using first func to simulate initial value const getValue = () => { return value; }; // The second function is to return the new value const updateValue = (newValue) => { // console.log(`Value 1 is now: ${newValue}`); return value = newValue; }; // Returning results in array return [getValue, updateValue]; } // Without destructuring const initialValue = useState(3); const firstValue = initialValue[0]; const secondValue = initialValue[1]; // Set new data console.log("Initial State", firstValue()); // 3 console.log("Final", secondValue(firstValue() + 5)); // 8 console.log("==========================="); // With destructuring const [counter, setCounter] = useState(0); console.log("Initial State", counter()); // 0 setCounter(counter() + 20); console.log("Final", counter());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM