我有一个子组件,我试图呈现并判断时间属性是否过期.

datasetData是我的父组件的props .

setInterval允许倒计时计时器按预期工作,然而,当一个过期事件被过滤,然后在我的setData中更新时,它会从对象中删除该项目,但是当在浏览器中显示时,对象中的新的第一个项目将显示时间0s,然后返回到它的适当剩余时间.

下面是我的子组件的标记:

function Item({ item, data, setData }) {

     useEffect(() => {
        const endTime = new Date(item.endTime);
        const itemID = item.itemId;

        const timeCheck = (endTime, itemID) => {

            let time = new Date();
    
            let ending = Math.floor(parseInt(endTime) - (time.getTime()/1000));
            let minutes = Math.floor(ending / 60);
            let seconds = ending % 60;
    
            if (minutes < 60 && minutes >=1 ) {
                setEndingTime(minutes + "m " + seconds + "s");
            } else if (minutes === 0) {
                setEndingTime(seconds + "s");
            }
            
            if (minutes <= 0 && seconds <= 0) {
                //console.log(itemID);
                //console.log(data);
                let newData = data.filter(item => item.itemId !== itemID);
                setData(newData);
            }
            //console.log(minutes + "m " + seconds + "s");
        }

        const intervalId = setInterval(() => {
            timeCheck(endTime.getTime()/1000, itemID)
        }, 1000);

        return () => clearInterval(intervalId);
    }, [item, data, setData]);

    return(
                    <div className="item__time">
                        Time Left: { endingTime }
                    </div>
    )
}

export default Item;

父组件:

function Tab({ setLoading }) {
    const [data, setData] = useState([]);

    const getItems = async () => {
        setLoading(true);
        try {
            const response = await fetch(‘local.api/endpoint’);
            const json = await response.json();
            setData(json);
        } catch (error) {
            console.log("Error", error);
        } finally {
            setLoading(false);
        }
    }

    useEffect(() => {
        getItems();
    }, []);

    return(
            <div className="tab">
                {data.length > 0 &&
                    data.map((item, index) => {
                        return(
                            <Item item={ item } data={ data } setData={ setData } key={`item__${ index }`} />
                        )
                    })
                }
          </div>
    )
}

export default Tab;

有什么 idea 可能导致渲染问题?

推荐答案

如果没有看到完整的代码并亲自运行它,这很难说,但我怀疑问题出在你使用key:

<Item item={ item } data={ data } setData={ setData } key={`item__${ index }`} />

React中的Keys应该 for each 项目提供一个uniquestable标识符,这样它就可以将组件与它们的状态进行匹配.对于简单的情况,或者对于没有真正改变的列表内容,您可以不使用列表索引;但是,对于更复杂的情况,使用索引可能会导致问题.例如,在这里,可能会发生以下情况:

  1. 初始列表在索引0 /键0处呈现为itemA,索引1 /键1处呈现为itemB.
  2. itemA<Item/>中呈现,它恢复其状态,激发其效果,等等,如你所愿
  3. 一旦itemA<Item/>的计时器变为0,它将从列表中删除itemA.
  4. 名单被重新呈现- and now 100 is at index 0 / key 0.
  5. 换句话说,itemB的键1<Item/>不是在列表中的新位置呈现,而是使用itemB重新呈现itemA的键0<Item/>.它保持它以前的任何状态(例如,它已经过期的时间).因为它的item已经改变,它重新激发它的效果,导致它重新初始化它的计时器.

如果你把你的 keys 改成key={item.itemId},那就可以了.(你不需要担心像item__前缀这样的东西- React需要键在单个列表中是稳定的和唯一的,但除此之外,它真的不在乎格式或字符串与数字.

Reactjs相关问答推荐

如何使用mui为可重复使用的react 按钮应用不同的风格

我想将状态设置为true,直到每一张卡片都生成并在多姆中呈现

包装组件可以避免子组件重新渲染.?

react 路由GUGUD Use Effect无法通过useNavigate正常工作

无法找出状态正在被更改的位置

Chart.js如何go 除边框

我无法通过 useContext 显示值

当`useSelector`回调中的属性值更新时,将会使用更新后的值吗?

React中useAuthenticator的authState在成功登录后仍保持未认证状态 - 需要强制刷新

如何在 JS 中绘制具有不同笔画宽度的样条线

如何覆盖自定义 MUI 手风琴的样式(分隔线和折叠图标)

在react 中单击父级中的按钮时如何将数据从子级发送到父级?

Stripe Checkout:是否可以创建不自动续订的订阅?

基于标记名的博客详细信息分组没有发生

顶点图表甜甜圈项目边框半径

React Native PermissionsAndroid 不包括 READ_MEDIA_IMAGES.如何解决这个问题?

setState 改变对象引用

Storybook - 无法解析generated-stories-entry.cjs/字段browser不包含有效的别名配置

react 页面更新

React 似乎在触发另一个组件时重新渲染了错误的组件