Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
249 views
in Technique[技术] by (71.8m points)

ReactJS custom hooks not keeping it's states

The Major scenario is I want to have a timer for getting new notifications, but sometimes I need to get notifications out of interval cycle that I have defined, so I put it in a useEffect wrapper, And I made a state in a customHook so I can change it from other components and I use that sate in my useEffect hook dependency list. Now I expect Compo1 to re run useEffect but it's not happening...

I have a project with this package.json:

{
  "name": "---",
  "version": "1.2.0",
  "private": true,
  "dependencies": {
    "@babel/runtime": "^7.7.7",
    "@date-io/jalaali": "^1.3.11",
    "@material-ui/core": "^4.11.2",
    "@material-ui/icons": "^4.11.2",
    "@material-ui/lab": "^4.0.0-alpha.57",
    "@material-ui/pickers": "^3.2.10",
    "@material-ui/styles": "^4.11.2",
    "animate.css": "^3.7.2",
    "axios": "^0.21.1",
    "clipboard-copy": "^3.1.0",
    "clsx": "^1.1.1",
    "dotenv": "^8.2.0",
    "env-cmd": "^10.0.1",
    "formik": "^2.0.8",
    "i18next": "^17.3.1",
    "jss": "^10.0.0",
    "jss-rtl": "^0.2.3",
    "lodash": "^4.17.15",
    "material-table": "^1.54.1",
    "material-ui-popup-state": "^1.6.1",
    "md5": "^2.2.1",
    "moment": "^2.24.0",
    "moment-jalaali": "^0.9.2",
    "notistack": "^0.9.7",
    "num2persian": "^3.1.3",
    "query-string": "^6.9.0",
    "react": "^17.0.1",
    "react-circular-progressbar": "^2.0.3",
    "react-detect-offline": "^2.4.0",
    "react-dom": "^17.0.1",
    "react-file-icon": "^1.0.0",
    "react-helmet": "^6.1.0",
    "react-i18next": "^10.13.2",
    "react-image": "^2.2.1",
    "react-minimal-pie-chart": "^6.0.1",
    "react-moment": "^0.9.6",
    "react-redux": "^7.2.2",
    "react-router": "^5.2.0",
    "react-router-dom": "^5.2.0",
    "react-scripts": "^4.0.1",
    "react-slidedown": "^2.4.5",
    "react-step-wizard": "^5.3.0",
    "react-toastify": "^5.5.0",
    "redux": "^4.0.5",
    "styled-components": "^4.4.1",
    "url-parse": "^1.4.7",
    "yup": "^0.28.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "prop-types": "^15.7.2",
    "typescript": "4.1.3"
  },
  "resolutions": {
  }
}

and I have two components and one custom hook with this contents

My custom hook:

export const useHeaderNotifUpdater = () => {
    const [signalUpate, dispatchUpdateNotifSignal]          = useState(true);
    console.log(signalUpate);
    return {signalUpate, dispatchUpdateNotifSignal};
};

Compo1:

import {connect} from "react-redux";
import withRouter from "react-router-dom/withRouter";

const Compo1 = ({history, balance, setBalance, setMobileVerifyStatus, userInfo}) => {
    const {signalUpate}                     = useHeaderNotifUpdater();
    const [notifs, setNotifs]               = useState(new Notifs({}));
    const [notifsLoading, setNotifsLoading] = useState(true);

    console.log('Compo1',signalUpate);
    useEffect(() => {

        let timeout = 0;

        const tick = () => {
            clearTimeout(timeout);

            api.notifs.getAllNotifis()
                .then(({data}) => {
                    setNotifs(new Notifs(data));
                })
                .catch(() => {
                })
                .finally(() => {
                    if (notifsLoading)
                        setNotifsLoading(false);
                    timeout = setTimeout(tick, 5000);
                })
        };
        tick();
        return () => {
            clearTimeout(timeout);
        };
        //eslint-disable-next-line
    }, [signalUpate]);

    return <div>{notifs?.length}</div>;

};

const mapStateToProps = state => ({
    balance          : state.auth.balance,
    isMobileNotVerify: state.auth.isMobileNotVerify,
    userInfo         : state.auth.userInfo,
});

const mapDispatchToProps = {
    logout,
    setBalance,
    setMobileVerifyStatus
};

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Compo1));

Compo2:

const Compo2 = () => {
    const {dispatchUpdateNotifSignal} = useHeaderNotifUpdater();
    const handleUpdateNotifs=()=>{
        dispatchUpdateNotifSignal(prevState => !prevState);
    }
    return <button onClick={handleUpdateNotifs}>Click me!</>;
};
export default Compo2;

The problem is the state is inside of my custom hook, is change from the outside, but never changes in Compo1 ! which is weird!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Each time you call your custom hook useHeaderNotifUpdater() it will create a new state. You should create only one state on the common parent component or create a global state with a context or a management state lib.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...