为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 vanilla JS 复制 useState

如何使用 vanilla JS 复制 useState

皈依舞 2023-07-20 16:05:04
Vanilla JS 中的代码的实现是什么,它允许我们像 React 中的 useState 那样声明和更新状态:const [x, setX] = useState(12);setX(14);console.log(x); // 14这道题严格来说是get better at JS。天真地说,这样搭配是有意义的:// Solution 1function 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 2class 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 ?我希望这是有道理的。
查看完整描述

5 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

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

这是实现:


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);


查看完整回答
反对 回复 2023-07-20
?
浮云间

TA贡献1829条经验 获得超4个赞

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


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 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!


查看完整回答
反对 回复 2023-07-20
?
POPMUISE

TA贡献1765条经验 获得超5个赞

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 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());


查看完整回答
反对 回复 2023-07-20
?
狐的传说

TA贡献1804条经验 获得超3个赞

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) // 0

like.value=2;

console.log(like.value) // 0

setLike(like.value + 1) 

console.log(like.value) // 1


查看完整回答
反对 回复 2023-07-20
?
慕码人8056858

TA贡献1803条经验 获得超6个赞

一个简单的解决方案来模拟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); // 0

setState({x:20});

console.log(state); // { x: 20 }

setState({x:30});

console.log(state); // { x: 30 }


查看完整回答
反对 回复 2023-07-20
  • 5 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信