我应该如何重用useState的React钩子setX?

时间:2019-02-15 21:37:38

标签: javascript reactjs

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

// 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('');。我不确定如果将其放到自己的函数中后如何重用,因为当前的示例错误提示我单击按钮时不在函数组件中。

我在useFriendStatus的{​​{3}}中看到了示例,如果可以使用效果来设置值,则基本上可以重用getter和setter。考虑到我想基于按下按钮来设置值,所以我不确定该做什么。

1 个答案:

答案 0 :(得分:1)

您应该做的是使用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>
}