0

我正在尝试在我的 React 应用程序中创建一个全局警报,该警报显示在屏幕顶部并且每个组件都可以使用。我有在 App 中使用的组件 GlobalAlert。

当我尝试从路由中的任何组件传递 GlobalAlert 的 setAlert 函数时,就会出现问题。我尝试像这样使用 React Refs:

const GlobalAlert = React.forwardRef((props, ref) => {
  const [variant, setVariant] = useState(null)
  const [message, setMessage] = useState(null)

  const setAlert = (vrnt, msg) => {
    setVariant(vrnt)
    setMessage(msg)
    setTimeout(() => {
      setMessage(null)
    }, 5000)
  }

  useImperativeHandle(ref, () => {
    return {
      setAlert,
    }
  })

  if (message) {
    return (
      <div>
        <Alert variant={variant}>{message}</Alert>
      </div>
    )
  }

  return (
    <div>
      <br />
      <br />
      <br />
    </div>
  )
})
const App = () => {
  const alertRef = React.createRef()

  const setAlert = (variant, message) => {
    alertRef.current.setAlert(variant, message)
  }

  return (
    <div className="container">
      <Router>
        <Menu />
        <GlobalAlert ref={alertRef} />
        <Routes setAlert={setAlert} />
      </Router>
    </div>
  )
}

当我在NewIngredient中的后端操作完成后尝试使用 setAlert 时:

const NewIngredient = ({ setAlert }) => {

  ...(excluded logic here)...

  const submit = async e => {
    e.preventDefault()
    try {
      await addIngredient({
        variables: {
          name: name.value,
          price: Number(price.value),
          ...(kcal.value && { kcal: Number(kcal.value) }),
        },
      })
    } catch (error) {
      console.log('Error adding ingredient in NewIngredient.js', error.message)
    }

    setAlert('success', `New Ingredient ${name.value} added!`)

    resetName()
    resetPrice()
    resetKcal()
  }

  return (
    <div>
      <Form onSubmit={submit}>
        <Form.Group>
          <Form.Label>Name</Form.Label>
          <Form.Control {...name} />
          <Form.Label>Price</Form.Label>
          <Form.Control {...price} />
          <Form.Label>Kcal</Form.Label>
          <Form.Control {...kcal} />
          <Button type="submit">Add ingredient</Button>
        </Form.Group>
      </Form>
    </div>
  )
}
Unhandled Rejection (TypeError): Cannot read property 'setAlert' of null

setAlert
src/App.js:27

  24 | const alertRef = React.createRef()
  25 | 
  26 | const setAlert = (variant, message) => {
> 27 |   alertRef.current.setAlert(variant, message)
  28 | ^ }
  29 |

submit
src/Ingredient/Forms/NewIngredient.js:49

  46 |   console.log('Error adding ingredient in NewIngredient.js', error.message)
  47 | }
  48 | 
> 49 | setAlert('success', `New Ingredient ${name.value} added!`)
  50 | ^  
  51 | resetName()
  52 | resetPrice() 

此外,如果我让它工作,它需要无意识的道具钻取组件结构。

如果可能的话,我宁愿不使用 Redux,因为我使用 Apollo 客户端来处理我所有应用程序的状态。我尝试使用 React Context API,但我发现无法为 NewIngredient 的提交函数传递 setAlert 函数。

有没有明确而简单的解决方案?

4

0 回答 0