Search code examples
javascriptreactjstoast

Toasty does not autoclose or manual close after hook list


I modified the code to generate a toast stack into a ToastContainer dynamically as a notification system. Now the toast do not autoclose even in close button click.

The code can be reproduced by copy and past inside of dimiss area in https://react-bootstrap.github.io/components/toasts/

const Tsty = (props) => 
    <>
    <Toast show={ props.show } delay={ 3000 } autohide>
      <Toast.Header>
        <img src="holder.js/20x20?text=%20" className="rounded me-2" alt="" />
        <strong className="me-auto">{props.title}</strong>
        <small className="text-muted">{props.time}</small>
      </Toast.Header>
      <Toast.Body>{props.body}</Toast.Body>
    </Toast>
    </>
render(<Tsty />);

function Example() {
  const [listNtfy, setNtfy] = useState([]);
  const style = { position: 'fixed', bottom: '60px', right: '10px', zIndex: '1000'}
  return (
    <>
    <Button onClick={() => {setNtfy([...listNtfy, {title: 'title #', time: 'now', body:  new Date().toString(), show : true }])}}>Add Ntfy</Button>
    <ToastContainer style={style}>
      { listNtfy.map( (x,i) => <Tsty show={ x.show } title={x.title + i} time={x.time} body={x.body} key={i} /> ) }
    </ToastContainer>
    </>
  );
}

render(<Example />);

where is the error?


Solution

  • This doesn't close cause Tosty hook to show property that is not present in the hook. To solve it, you can define the show property and create a function to hide it. When all ntfys are closed, the list is cleaned.

    const Tsty = (props) => 
        <>
        <Toast show={ props.show } onClose={ () => {props.fcn(props.idx) } } delay={ 5000 } autohide>
          <Toast.Header>
            <img src="holder.js/20x20?text=Q" className="rounded me-2" alt="" />
            <strong className="me-auto">{props.title}</strong>
            <small className="text-muted">{props.time}</small>
          </Toast.Header>
          <Toast.Body>{props.body}</Toast.Body>
        </Toast>
        </>
    render(<Tsty />);
    
    function Example() {
      const [listNtfy, setNtfy] = useState([]);
      // Function to autohide the ntfys
      const autoHide = (key) => { 
        // Set visibility of Ntfy to hidden
        listNtfy.filter((x,i) => i === key)[0].show = false;
        // Apply the change
        setNtfy([...listNtfy]);
        // Check all notifications is hide (if yes, reset the list)
        if (listNtfy.every(v => v.show === false))
          setNtfy([]);
        };
      const style = { position: 'fixed', bottom: '60px', right: '10px', zIndex: '1000'}
      return (
        <>
        <Button onClick={() => {setNtfy([...listNtfy, { title: 'title #' + listNtfy.length, time: 'now', body:  new Date().toString(), show : true }])}}>Add Ntfy</Button>
        <ToastContainer style={style}>
          { listNtfy.map( (x,i) => <Tsty show={ x.show } title={x.title} time={x.time} body={ x.body } key={i} idx={i} fcn={ autoHide } /> )}
        </ToastContainer>
        </>
      );
    }
    
    render(<Example />);