首页 > 解决方案 > 我应该如何重用来自 useState 的 React hooks setX?

问题描述

我有两个组件基本上是这样的:

// use-error-msg.jsx
function useErrorMsg(defaultMessage) {
  const [errorMsg, setError] = useState(defaultMessage);

  return errorMsg;
}

// Layout.jsx
function Layout() {
  const errorMsg = useErrorMsg('');
  const error = (errorMsg) ? <div>{errorMsg}</div> : ''
  return <div>
    {error}
    <ComponentWithButton />
  </div>
}

// ComponentWithButton.jsx
function ComponentWithButton() {
  return <div>
    <button onClick={() => {useErrorMsg('Something failed')}}>Click</button>
  </div>
}

我知道我能做到const [errorMsg, setErrorMsg] = setState('');。考虑到我当前的示例错误,即单击按钮时我不在功能组件中,我不确定如果将其放入自己的函数中,它如何重新使用。

我在docs中看到了示例,useFriendStatus如果您可以使用效果设置值,这基本上可以让您重用 getter 和 setter。考虑到我想根据点击按钮来设置值,我不确定我要做什么。

标签: javascriptreactjs

解决方案


你应该做的是使用你的 setError 函数来改变状态。如您所见,我将 setError 函数向下传递给组件。如果你想更深入,也许检查useContext

// use-error-msg.jsx
function useErrorMsg(defaultMessage) {
  const [errorMsg, setError] = useState(defaultMessage);

  return [errorMsg, setError];
}


// Layout.jsx
function Layout() {
  const [errorMsg, setError] = useErrorMsg('');
  const error = (errorMsg) ? <div>{errorMsg}</div> : ''
  return <div>
    {error}
    <ComponentWithButton setError={setError} />
  </div>
}

// ComponentWithButton.jsx
function ComponentWithButton(props) {
  return <div>
    <button onClick={() => {props.setError('Something failed')}}>Click</button>
  </div>
}

带有上下文的示例。https://codesandbox.io/s/l90p3023yl

// use-error-msg.jsx
function useErrorMsg(defaultMessage) {
  const [errorMsg, setError] = useState(defaultMessage);

  return [errorMsg, setError];
}

// error-context.jsx
import React from 'react';

const ErrorContext = React.createContext()

function ErrorProvider(props) {
  const [errorMsg, setError] = useErrorMsg('');

  return (
    <ErrorContext.Provider value={{ errorMsg, setError }}>
      {props.children}
    </ErrorContext.Provider>
  )
}

// App.jsx

function App() {
  return (
    <ErrorProvider>
      <Layout />
    </ErrorProvider>
  )
}

// Layout.jsx
function Layout() {
  const { errorMsg } = useContext(ErrorContext);
  const error = (errorMsg) ? <div>{errorMsg}</div> : ''
  return <div>
    {error}
    <ComponentWithButton />
  </div>
}

// ComponentWithButton.jsx
function ComponentWithButton(props) {
  const { setError } = useContext(ErrorContext);
  return <div>
    <button onClick={() => {setError('Something failed')}}>Click</button>
  </div>
}

推荐阅读