React useEffect 钩子在后坐力原子更新后不调用

问题描述

我使用 recoiljs 作为我的 React 项目的状态管理器,当反冲原子从另一个文件更改时,我的一个组件不会调用它的 useEffect。这是我从原子读取的主要组件。

import React,{useState,useEffect} from 'react'
import '../css/MeadDeadline.css'
import {getNearestDate} from '../chromeAPI/retrieveDeadlineJSON'

import DeadlineList from '../atoms/deadlinelist'
import {useRecoilValue} from 'recoil'

export default function MainDeadline() {
    // get the date and the stuff from chrome storage
    const [school,setSchool] = useState("");
    const [date,setDate] = useState("");
    let [deadlinelist,setDeadlineList] = useRecoilValue(DeadlineList);

    useEffect(() => {
        const nearest = getNearestDate(deadlinelist);
        const len = nearest.length;

        if (len === 0){
            setSchool("No schools registered");
            setDate("");

        } else if (len === 1){
            setSchool(nearest[0].school);
            setDate(nearest[0].date);
            
        } else {
            // we need to render a lot of stuff
            console.log("error");
        }

    },[deadlinelist]);

    return (
        <>
            <div className="MainDeadline">
                <div className='school'>{school}</div>
                <div classNmae='date'>{date}</div>
            </div>
        </>
    )
}

这是我的原子文件

import {atom} from 'recoil'

const DeadlineList = atom({
    key: "deadlinelist",default: []
}); 
export default DeadlineList;

这是我提交的表格

import React,{useState} from 'react'
import '../css/InputForm.css'
import checkList from '../utils/checkList'
import checkDate from '../utils/checkDate'
import {storeNewDeadline} from '../chromeAPI/storeNewDeadline'

import {useRecoilState} from 'recoil'
import DeadlineList from '../atoms/deadlinelist'
import SchoolList from '../atoms/schoollist'

export default function InputForm () {
    const [inputschool,setInputSchool] = useState('');
    const [inputdate,setInputDate] = useState('');
    const [invalidschool,setInvalidSchool] = useState(false);
    const [invaliddate,setInvalidDate] = useState(false);
    const [badschool,setBadSchool] = useState('');
    const [baddate,setBadDate] = useState('');

    const [schoollist,setSchoolList] = useRecoilState(SchoolList);
    const [deadlinelist,setDeadlineList] = useRecoilState(DeadlineList);

    const validateForm = () => {
        // check to make sure its not in the list
        const valschool = checkList(schoollist,inputschool);
        if (!valschool){
            setInvalidSchool(true);
            setBadSchool(inputschool);
        } else {
            setInvalidSchool(false);
            setBadSchool("");
        }
        // check to make sure the date hasnt been reached yet
        const valdate = checkDate(inputdate);
        if (!valdate){ // add MSIN1DAY becauase the day value is 0 indexed so conflicts with Date() and date input
            setInvalidDate(true);
            setBadDate(inputdate);
        }
        else {
            setInvalidDate(false);
            setBadDate("");
        }

        return !invalidschool && !invaliddate; // want both to be valid
    }

    const handleSubmit = async(event) => {
        event.preventDefault();
        
        // validate the form
        if (validateForm()){
            storeNewDeadline(inputschool,inputdate);

            // change schoollist state
            let slist = schoollist;
            slist.push(inputschool);
            setSchoolList(slist);

            // change deadlinelist state
            let dlist = deadlinelist;
            dlist.push({
                "school": inputschool,"date": inputdate
            });
            setDeadlineList(dlist);

            console.log(deadlinelist,schoollist);
        }
    }

    const handleChange = (event,fieldname) => {
        switch (fieldname) {
            case "inputschool":
                setInputSchool(event.target.value);
                break;
            
            case "inputdate":
                setInputDate(event.target.value);
                break;
            
            default:
                break;
        }
    }

    return (
        <form className='InputForm' onSubmit={handleSubmit}>
            <h3>Enter New School</h3>

            <div id='inputname' className='Inputer'>
                <p>School Name</p>
                <input 
                    type='text'
                    onChange={e => {handleChange(e,'inputschool')}}
                    value={inputschool}
                    required 
                />
                {invalidschool ? <p>{badschool} is already registered</p> : null}
            </div>

            <div id='inputdate' className='Inputer'>
                <p>Deadline Date</p>
                <input
                    type='date'
                    onChange={e => {handleChange(e,'inputdate')}}
                    value={inputdate}
                    required
                />
                {invaliddate ? <p>{baddate} is invalid</p> : null}
            </div>

            <div id='inputsubmit' className='Inputer'>
                <p>Submit</p>
                <input type='submit' required></input>
            </div>
            
        </form>
    )
}

如果您只想查看文件文件,则 github 为 here 主要组件是 src/components/MainDeadline.jsx,src/atoms/deadlinelist,src/components/InputForm.jsx

我的主要问题是当用户在表单中输入内容时,它应该更新状态,但主要组件没有更新。

请告诉我是否可以以任何方式改进我的代码,这是我的第一个 React 项目。

解决方法

在 state hook 中处理数组时,需要像执行 set 函数一样克隆数组。

另外,代替这个: 让 [deadlinelist,setDeadlineList] = useRecoilValue(DeadlineList);

我会这样做: const [deadlinelist,setDeadlineList] = useRecoilState(DeadlineList);

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...