在声明之前,React Hooks从useState访问状态

时间:2019-06-17 08:14:51

标签: javascript reactjs react-hooks

我正在尝试了解React挂钩如何与我设置的简单身份验证模式一起工作。我有一个处理表单状态的自定义useForm钩子,我很好奇我如何在声明之前访问values

function LoginModal () {
   console.log('outside values', values) // undefined
   const submitForm = async () => {
     console.log('inside values', values) // email, password values exist
     const request = {
        method: 'POST',
        url: '/auth/login',
        data: {
           email: values.email,
           password: values.password
        }
    }
    await axios(request)
  }

  const [values, handleChange, handleSubmit] = useForm(submitForm)

  return <div>some form stuff</div>
}

`useForm.js`

import { useState } from 'react'

const useForm = submitForm => {
  const [state, setState] = useState({})

  const handleChange = event => {
    event.persist()
    setState(state => ({ ...state, [event.target.name]: event.target.value }))
  }

  const handleSubmit = event => {
    event.preventDefault()
    submitForm()
  }

  return [state, handleChange, handleSubmit]
}

export default useForm


有人可以向我解释为什么values仅存在于submitForm函数中,以及在声明const [values]之前它如何可用?我相信const声明不会被悬挂。谢谢!

1 个答案:

答案 0 :(得分:1)

当您声明一个函数时,JS将把该函数声明保留在内存中,并提供对其各自本地和全局范围的访问。这就是您的submitForm函数所发生的事情。在下面摘录的示例中,这是someFunc函数。

从下面的示例中可以看到,如果在声明变量values之前执行,将得到undefined。因为它不在范围内。

但是,如果您像执行操作一样通过click事件执行函数,则在定义变量values ,您的函数将能够“看到”该变量,因为它已经在范围内。

注意:您是正确的。 const声明未悬挂。

function App() {
  
  // WHEN YOU CALL IT THROUGH A CLICK EVENT, THE VARIABLE `values` WILL BE IN SCOPE
  function someFunc() {
    console.log('State from someFunc(): ' + values);
  }
  
  console.log('State from component body BEFORE variable "values" declaration: ' + values);
  
  someFunc(); // WHEN EXECUTED AT THIS POINT. IT HAS NO ACCESS TO 'values' BECAUSE IT'S STILL undefined
  
  const [values,setValues] = React.useState(['a','b','c']);
  
  console.log('State from component body AFTER variable "values" declaration: ' + values);
  
  return(
    <button onClick={someFunc}>Click to run someFunc()</button>
  );
}

ReactDOM.render(<App/>,document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>