如何合并状态和道具以控制 React 中警报的可见性

How can I merge state and props to control visibility of alert in React

我有一个默认情况下不可见的警报组件,当父组件中发生某些事情(例如单击)时,警报组件将可见。在 alert 组件内部,有一个关闭按钮可以使组件再次不可见。我是react新手,发现很难实现。

这是我目前的解决方案:

警报组件:

import React, {useEffect, useState} from "react";

const Alert = ({show, style, message}) => {

    const [visibility, setVisibility] = useState(show);

    useEffect(() => {
        setVisibility(show);
    },[show]);

    return (
        <>
        {(visibility)?(
            <div className="col">
              <div className={"alert shadow alert-"+style} role="alert">
                {message}
                <button type="button" className="close" aria-label="Close" onClick={(e) => {
                  setVisibility(false);
                }}>
                  <span aria-hidden="true">&times;</span>
                </button>
              </div>
            </div>
        ):(<></>)}
        </>
    );


}

export default Alert;

父组件有一个状态来管理它。

const [alert, setAlert] = useState({
    'show': false,
    'style':'',
    'message':''
  });
<Alert show={alert.show} style={alert.style} message={alert.message} />
<button onClick={(e) => {

  setAlert({
    'show':false, 
    'style':'',
    'message':''
  });
  setAlert({
    'show':true, 
    'style':'success',
    'message':'Thank you!'
  });
}>
  show
</button>

问题是因为当我点击父组件中的按钮时,点击警告组件中的关闭按钮时属性show没有改变,所以属性show仍然是true 所以它不会呈现警报组件。我使用的解决方法是将警报属性 show 设置为 false,然后再将其设置为 true。这不是很整洁。有没有更好的方法结合 prop 和 state 来决定警报的可见性?

您需要定义一个函数来隐藏父组件本身的Alert,并将其传递给子组件。

const hideAlert = () => {
   setAlert(prevState => ({
     ...prevState,
     show: !prevState.show
   }))
}

然后你可以将它传递给Alert组件,

<Alert show={alert.show} style={alert.style} message={alert.message} hideAlert={hideAlert}/>

在alert组件中,无需再将props存入state。你应该直接使用道具,

const Alert = ({show, style, message, hideAlert}) => {
  return (
    <>
      { show ? <div className="col">  //directly use props here to show alert
          <div className={"alert shadow alert-"+style} role="alert">
            {message}
            <button type="button" className="close" aria-label="Close" onClick={hideAlert}>
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
        </div>
        : 
        <></>
      }
    </>
  );
}

Demo