如何使用 vanilla JS 复制 useState

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


const [x, setX] = useState(12);

setX(14);

console.log(x); // 14

这道题严格来说是get better at JS。天真地说,这样搭配是有意义的:


// 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 ?我希望这是有道理的。


皈依舞
浏览 159回答 5
5回答

暮色呼如

我也想学习如何实现这一目标。我重构了代码以使用箭头函数,这会使代码片段更难以阅读和理解。如果是这种情况,请访问上面链接中共享的资源。这是实现: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 valueconsole.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);

浮云间

您缺少一些非常重要的东西 - 所有反应钩子都使用一些“支持”它们的东西,当您没有实例时,您只有一个函数,这允许您提供有效的实例变量。React 中的这个东西被称为 Fiber,它有效地代表了 React 组件的生命周期 - 它本身并不依赖于函数本身,它依赖于 React 正在渲染(和重新渲染)的组件。这就是为什么你可以有一个功能组件声明,多次渲染同一个函数,并且每个函数都能够维护自己的状态 - 状态不是函数的一部分,状态是 React Fiber 的一部分。但我不明白数组 [x, setX] 如何有一个回调(setX),当用 const 声明时会影响 x ?当你调用 时,你并不是简单地改变 x 的值setX,你所做的是告诉 React 使用新的 x 值重新渲染组件(纤程)。编辑:一个非常简单的示例,其中函数本身用作状态的支持实例(React 中不是这种情况)可能如下所示:// this line is example only so we can access the stateSetter external to the functionlet 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 changedstateSetter('new state'); // state has been updated!

POPMUISE

1.- 函数返回值的解构。我们应用它来解构函数返回的数组的两个值。第一个值将返回变量的当前数据,第二个值将具有该值的更改函数。// 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 destructuringconst initialValue = useState(3);const firstValue = initialValue[0];const secondValue = initialValue[1];// Set new dataconsole.log("Initial State", firstValue()); // 3console.log("Final", secondValue(firstValue() + 5)); // 8console.log("===========================");// With destructuringconst [counter, setCounter] = useState(0);console.log("Initial State", counter()); // 0setCounter(counter() + 20);console.log("Final", counter());

狐的传说

class useState {    constructor(defaultt=""){         this.state = { value: defaultt}        const handler = {                set: () => {                    return false                }            }        const data = new Proxy(this.state,handler);        const stateBind = this.setState.bind(this)        return [data, stateBind];    }    setState(variable){        this.state.value = variable    }}const [like,setLike] = new useState(0)console.log(like.value) // 0like.value=2;console.log(like.value) // 0setLike(like.value + 1) console.log(like.value) // 1

慕码人8056858

一个简单的解决方案来模拟useState()使用构造函数。这可能不是最好的解决方案,因为构造函数每次都会返回函数的副本,但可以解决所讨论的问题。function Hook(){  return function (initialState){    this.state = initialState;    return [      this.state,      function(newState){        this.state = newState;      }    ];  }}const useState = new Hook();现在,解构 ituseState()的一个实例Hook()const [state, setState] = useState(0);console.log(state); // 0setState({x:20});console.log(state); // { x: 20 }setState({x:30});console.log(state); // { x: 30 }
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript