react hooks & component will unmount & useEffect & clear up
阅读原文时间:2023年07月09日阅读:1

react hooks & component will unmount & useEffect & clear up

useEffect & return === unmounted

import React, {
  // Component,
  useState,
  // useRef,
  useEffect,
} from 'react';

import { getTrackPicsIdImg } from '@/services';

import "./index.css";

import {
  Icon,
  Popover,
} from "antd";

const IconsSlot = (props) => {
  const [unmount, setUnmount] = useState(false);
  const [url, setUrl] = useState(null);
  const [visible, setVisible] = useState(false);

  useEffect(() => {
    // clear up === unmounted
    return () => {
      setUnmount(true);
    };
  }, [unmount]);

  const handleVisibleChange = () => {
    if(!unmount) {
      setVisible(false);
    }
  };

  const gotoUserPageById = (id = ``, type = ``, callback) => {
    callback(id);
    if(id) {
      alert(`got user page`, id, type);
    }
  };

  const showScreenShots = (id = ``, type = ``, callback) => {
    // callback(id, type);
    if(id) {
      getTrackPicsIdImg(id)
      .then(res => {
        const {
          url,
        } = res.data;
        if(url) {
          if(!unmount) {
            setVisible(true);
            setUrl(url);
          }
        } else {
          if(!unmount) {
            setVisible(false);
          }
        }
        // console.log(`res.data`, res.data);
      });
    }
  };
  const {
    icons,
    options,
    idCallback,
    screenShotCallback,
  } = props;
  const {
    // url,
    id,
    type,// 1 是页面; 2 是控件
  } = options;
  return(
    <>
      {
        icons[0]
        &&
        <span className="icon-user-box" onClick={() => gotoUserPageById(id, type, idCallback)}>
          <Icon type="user" className="space-span" />
        </span>
      }
      {
        !icons[1]
        &&
        <span className="icon-image-box" onClick={() => showScreenShots(id, type, screenShotCallback)}>
          <Popover
            content={
              <img
                src={url}
                alt="截图"
                className="image-screenshot"
              />
            }
            visible={visible}
            trigger="click"
            onVisibleChange={handleVisibleChange}
          >
            <Icon type="file-image" className="space-span" />
          </Popover>
        </span>
      }
    </>
  );
};

export default IconsSlot;

https://stackoverflow.com/questions/53464595/how-to-use-componentwillmount-in-react-hooks


react hooks & need inside function

bug

// ?

// import React from "react";
// import { connect } from 'dva';
import React, {
  // Component,
  // useRef,
  useState,
  // useEffect,
} from 'react';
// import ReactDOM from 'react-dom';

import { getTrackPicsIdImg } from '@/services';
// import { checkFetchIsAborting } from '@/utils/urlUtils';

import "./index.css";

import {
  Icon,
  // Modal,
  Popover,
} from "antd";

const IconsSlot = (props) => {
  // const imageRef = useRef(null);
  const [url, setUrl] = useState(null);
  const [visible, setVisible] = useState(false);

  const handleVisibleChange = () => {
    setVisible(false);
  };

  const gotoUserPageById = (id = ``, type = ``, callback) => {
    callback(id);
    if(id) {
      alert(`got user page`, id, type);
    }
  };

  const showScreenShots = (id = ``, type = ``, callback) => {
    // callback(id, type);
    // const dom = ReactDOM.findDOMNode(imageRef.current);
    if(id) {
      getTrackPicsIdImg(id)
      .then(res => {
        const {
          url,
        } = res.data;
        if(url) {
          setVisible(true);
          setUrl(url);
          // Modal.info({
          //   wrapClassName: "image-screenshot-box",
          //   title: '截图',
          //   content: (
          //     <div>
          //       <img
          //         src={url}
          //         // src="http://s1.xmcdn.com/yx/user-analysis-fe/last/dist/static/logo.6ecf7074.png"
          //         alt="screenshot"
          //         className="image-screenshot"
          //       />
          //     </div>
          //   ),
          //   onOk() {},
          //   okText: "关闭",
          // });
        } else {
          setVisible(false);
        }
        // console.log(`res `, res);
        console.log(`res.data`, res.data);
      });
    }
  };
  const {
    icons,
    options,
    idCallback,
    screenShotCallback,
  } = props;
  const {
    // url,
    id,
    type,// 1 是页面; 2 是控件
  } = options;
  return(
    <>
      {
        icons[0]
        &&
        <span className="icon-user-box" onClick={() => gotoUserPageById(id, type, idCallback)}>
          <Icon type="user" className="space-span" />
        </span>
      }
      {
        !icons[1]
        &&
        <span className="icon-image-box" onClick={() => showScreenShots(id, type, screenShotCallback)}>
          <Popover
            content={
              <img
                src={url}
                alt="截图"
                className="image-screenshot"
              />
            }
            visible={visible}
            trigger="click"
            onVisibleChange={handleVisibleChange}
          >
            <Icon type="file-image" className="space-span" />
            {/* <Icon type="file-image" className="space-span" ref={imageRef} /> */}
          </Popover>
        </span>
      }
      {/* {
        !icons[1]
        &&
        <span className="icon-image-box" onClick={() => showScreenShots(id, type, screenShotCallback)}>
          <Icon type="file-image" className="space-span" ref={imageRef} />
        </span>
      } */}
    </>
  );
};

export default IconsSlot;

OK

import React, {
  useState,
  useEffect,
  useRef,
} from 'react';
import ReactDOM from 'react-dom';

import StepBox from './StepBox';
import ChartBox from './ChartBox';

import {
  STEPS,
} from './STEPS';

import "./index.css";

import {
  Row,
  Col,
} from "antd";

const stepsShaper = (steps = [], total = 0) => {
  const len = steps.length;
  return steps.map(
    (obj, i) => {
      const index = i + 1;
      const {
        id,
        name,
        count,
        type,
        screenshot,
      } = obj;
      return {
        id,
        title: name,
        num: count,
        type,
        url: screenshot,
        value: (index === len) ? total : steps[index].transRate,
      };
    }
  );
};

const StepsGenerator = (props) => {
  const widthRef = useRef(null);
  const refClick = () => {
    const dom = ReactDOM.findDOMNode(widthRef.current);
    const width = dom ? dom.getBoundingClientRect().width : 50;
    return width - 50;
  };
  const [width, setWidth] = useState(null);
  useEffect(() => {
    const width = refClick();
    setWidth(width);
  }, [width], refClick);
  const {
    titleSlot,
    iconsSlot,
    dataSource,
  } = props;
  const {
    steps,
    total,
  } = dataSource;
  if(!steps.length) {
    return(
      <Row>
        <Col span={24}>
          <div className="funel-chart-no-data">
            暂无数据!
          </div>
        </Col>
      </Row>
    );
  }
  return stepsShaper(steps, total).map((data, i) => {
    return (
      <Row className="funnel-chart-container" key={`uid_100${i}`}>
        <Col span={8} className="step-box">
          <StepBox
            step={STEPS[i]}
            data={data}
            titleSlot={titleSlot}
            iconsSlot={iconsSlot}
          />
        </Col>
        <Col span={16} className="chart-box" ref={widthRef}>
          <ChartBox
            isFirst={i === 0}
            data={data}
            refClick={refClick}
          />
        </Col>
      </Row>
    );
  });
};

const FunnelChart = (props) => {
  const {
    titleSlot,
    iconsSlot,
    dataSource,
  } = props;
  return (
    <>
      <StepsGenerator
        titleSlot={titleSlot}
        iconsSlot={iconsSlot}
        dataSource={dataSource}
      />
    </>
  );
};

export default FunnelChart;