钩子从子组件重新渲染更新数组项

时间:2021-05-30 17:13:43

标签: javascript reactjs react-hooks

我有一个钩子可以在应用程序中显示一系列警报。每次我调用钩子推送数组并显示新警报时,它都可以正常工作,但如果我想从子组件中删除此警报,则调用父钩子函数不起作用。

这是警报组件。 “closeAlert”道具是调用父钩子函数的道具。 该方法被调用,它从数组中删除我想要的元素,但它不会使用数组的新值呈现

import React from 'react';
import { Alert, Button } from '@themesberg/react-bootstrap';
import { memo } from 'react';
import { createPortal } from 'react-dom';

const Alerts = memo(({ content, closeAlert, i }) => {
  const domEl = document.getElementById('alerts')
  if (!domEl) return null

  return createPortal(
    <React.Fragment>
      <Alert
        variant="primary">

        <div className="d-flex  align-items-center justify-content-between">
          <div className="font-small">
            {content.body}
          </div>
          <Button variant="close" size="xs" onClick={() => closeAlert(i)} />
        </div>
      </Alert>
    </React.Fragment>,
    domEl
  );
})

export default Alerts;

这是钩子。当我调用 Alerts 组件时,我将“handleCloseAlert”函数作为道具传递。正如我在上一点所说的。从警报中,它可以毫无问题地调用此函数,并删除所需的“hiddenAlerts”数组元素,但永远不会在“RenderAlert”中更新或呈现它

import React from 'react';
import { useState } from 'react';
import { Fragment } from 'react';
import Alerts from '../components/Alerts';

const useAlert = () => {
    const [hiddenAlerts, setHiddenAlerts] = useState([]);

    const handleShowAlert = (alertId) => {
        const hiddenAlertsUpdated = [...hiddenAlerts, alertId];
        setHiddenAlerts(hiddenAlertsUpdated);
    };

    const handleCloseAlert = (alertId) => {
        const alerts = hiddenAlerts;
        alerts.splice(alertId, 1);
        setHiddenAlerts(alerts);
    };

    const RenderAlert = () => (
        <Fragment>
            {
                hiddenAlerts.map((res, index) => {
                    return <Alerts key={index} content={res} i={index} closeAlert={handleCloseAlert}></Alerts>
                })
            }
        </Fragment>
    )

    return {
        handleShowAlert,
        handleCloseAlert,
        RenderAlert
    }
};

export default useAlert;

从这里我调用钩子

export default (props) => {
  const { handleShowAlert, RenderAlert } = useAlert();

  const open = () => {
    const alert = new AlertModal(
      "Alert test",
      '',
      Constants.TYPE_ALERT.warning
    )
    handleShowAlert(alert);
  }

  return (
    <div>
      <Button variant="primary" type="button" onClick={open} className="w-100">Abrir modal</Button>
      <RenderAlert>
      </RenderAlert>
    </div>
  )
}

从已经非常感谢你

2 个答案:

答案 0 :(得分:0)

可能问题出在修改当前数组的splice函数的使用,所以hiddenAlerts数组保持相同的引用。您可以改为使用 filter 函数创建一个新数组,如下所示:

const handleCloseAlert = i => {
  const newAlerts = hiddenAlerts.filter((_, index) => i !== index);
  setHiddenAlerts(newAlerts);
}; 

答案 1 :(得分:0)

这是因为在您的 handleCloseAlert 实现中,alerts 是对您的状态对象 hiddenAlerts 的引用。执行 splice 并使用 setHiddenAlerts(alerts) 更新状态确实如此不会触发状态更改,因为 react 在 hiddenAlerts 中看不到任何变化(因为 alerts 也是相同的 [reference] )

你可以试试下面的实现

 const handleCloseAlert = (alertId) => {
        setHiddenAlerts(hiddenAlerts.filter((_, index) => index !== alertId));
    };

此外,尝试将此实现更改为不依赖于数组索引值。尝试使用像 uuid

这样的库