简体   繁体   中英

React.js: Possible to assign useState() outside function component?

Is there any syntax that would allow assigning useState outside of the function component? I have tried this so far but it has not worked:

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function App() {
  useEffect(() => setStateData("from useEffect"), []);

  return <div className="App">{stateData}</div>;
}

const [stateData, setStateData] = App.useState("default value"); // fails
// const [stateData, setStateData] = App.prototype.useState("default value"); // also fails

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

CodeSandbox: 编辑 objective-worker-qb20h

You can use the useState 's update function outside of a component by assigning it to a variable. Just be sure to clear it when the component unmounts.

/* Reference to hold the update function */
let updateOutside

function App() {
  const [state, update] = useState()
  
  useEffect(() => {
    /* Assign update to outside variable */
    updateOutside = update

    /* Unassign when component unmounts */
    return () => updateOutside = null
  })

  return `App State: ${state}`
}

if (updateOutside) updateOutside(/* will re-render App */)

Is there any syntax that would allow assigning useState outside of the function component?

If you take a look at the docs and Rules of Hooks

Only Call Hooks from React Functions

Don't call Hooks from regular JavaScript functions. Instead, you can:

✅ Call Hooks from React function components.
✅ Call Hooks from custom Hooks (we'll learn about them on the next page).

So... no, you can't use useState outside of a functional component.

If you want to use useState outside of components think about using https://jotai.org/

It's useState replacement with some additional bonuses

 import { atom, useAtom } from 'jotai'

// Create your atoms and derivatives
const textAtom = atom('hello')
const uppercaseAtom = atom(
  (get) => get(textAtom).toUpperCase()
)

// Use them anywhere in your app
const Input = () => {
  const [text, setText] = useAtom(textAtom)
  const handleChange = (e) => setText(e.target.value)
  return (
    <input value={text} onChange={handleChange} />
  )
}

const Uppercase = () => {
  const [uppercase] = useAtom(uppercaseAtom)
  return (
    <div>Uppercase: {uppercase}</div>
  )
}

// Now you have the components
const App = () => {
  return (
    <>
      <Input />
      <Uppercase />
    </>
  )
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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