在 React 应用程序中添加项目时,项目列表未更新

Posted

技术标签:

【中文标题】在 React 应用程序中添加项目时,项目列表未更新【英文标题】:Item list is not updated when item is added in React app 【发布时间】:2021-09-10 00:19:27 【问题描述】:

我使用 React、MongoDB 和 axios 创建了一个项目列表。

但是,有时新添加的项目只有在手动重新加载浏览器时才会出现在屏幕上(我假设必须重新渲染列表组件,但我不知道该怎么做)。

ExpenseAmountInputContainer.tsx(项目已添加到此组件中

import React,  useState  from 'react';
import InputItem from './InputItem';
import AddButton from './AddButton';
import ErrorMessage from './ErrorMessage';
import  ExpenseAndAmountObject  from '../ExpenseAndAmountObject';
import axios from 'axios';
interface Props 
    expenseAndAmountList: Array<ExpenseAndAmountObject>;
    setExpenseAndAmountList: (value: Array<ExpenseAndAmountObject>) => void;
    setTotalExpensesAmount: (value: any) => void;
    totalExpenses: number; 


const ExpenseAmountInputContainer: React.FC<Props> = (
        
            expenseAndAmountList, 
            setExpenseAndAmountList,
            setTotalExpensesAmount,
            totalExpenses,
        : Props
    ) => 
    
    const [Expense, setExpense] = useState<string>('');
    const [Amount, setAmount] = useState<string>('');
    const [ifNotValidInputs, setIfNotValidInputs] = useState<boolean>(false);

    const AddItemToList = () => 
        if (Expense !== '' && Amount !== '' && Number(Amount) > 0) 

            axios.post('http://localhost:4000/app/expenseslist', 
            
                expenseTitle: Expense,
                expenseAmount: Amount
            );
            
            const newTotalExpense = totalExpenses + Number(Amount);
            setTotalExpensesAmount(newTotalExpense);

            axios.delete('http://localhost:4000/app/totalexpensesamount') 
            .catch(function (error) 
                console.log(error);
            );

            axios.post('http://localhost:4000/app/totalexpensesamount', 
            
                totalExpensesAmount: newTotalExpense
            );
            
            setExpense("");
            setAmount("");
            setIfNotValidInputs(false);
         else 
            setIfNotValidInputs(true);
        

        const expensesListResp = async () => 
            await axios.get('http://localhost:4000/app/expenseslist')
            .then(
            response => setExpenseAndAmountList(response.data && response.data.length > 0 ? response.data : []));
        
        expensesListResp();
    

    return (
        <div>
            <InputItem 
                onChange=setExpense 
                onBlur=setExpense 
                title="Expense" 
                type="text" 
                placeholder="Item title" 
                value=Expense           
            />
            <InputItem 
                onChange=setAmount  
                onBlur=setAmount  
                title="Amount" 
                type="number" 
                placeholder="Expense cost" 
                value=Amount
            
            />
            <AddButton 
                onClick=AddItemToList 
                content="Add expense"
            />
             ifNotValidInputs === true ? <ErrorMessage className="error-message"/> : null 
        </div>
    );
;

export default ExpenseAmountInputContainer;

DynamicList.tsx(项目列在此组件中

import React from "react";
import  List  from "@material-ui/core";
import ExpensesListItem from './ExpensesListItem';
import  ExpenseAndAmountObject  from '../ExpenseAndAmountObject';
  interface ListItemsArray 
    expenseAndAmountList: Array<ExpenseAndAmountObject>;
    currencySymbol: string;
    setExpenseAndAmountList: (value: Array<ExpenseAndAmountObject>) => void;
  

  const DynamicList: React.FC<ListItemsArray> = (
    
      expenseAndAmountList, 
      currencySymbol,
      setExpenseAndAmountList
    : ListItemsArray) => 

    return (
        <>
            <List>
                expenseAndAmountList.map(item => (
                  <ExpensesListItem
                    key=item._id
                    id=item._id
                    expenseTitle=item.expenseTitle 
                    expenseAmount=item.expenseAmount
                    currencySymbol=currencySymbol
                    item=item
                    expenseAndAmountList=expenseAndAmountList
                    setExpenseAndAmountList=setExpenseAndAmountList
                  />
                )) 
            </List>
        </>
      );
  
  
export default DynamicList;

ExpensesListItem.tsx

import React from "react";
import  IconButton, ListItem, ListItemSecondaryAction, ListItemText  from "@material-ui/core";
import DeleteIcon from '@material-ui/icons/Delete';
import  ExpenseAndAmountObject  from '../ExpenseAndAmountObject';
import axios from 'axios';
interface Props 
    expenseTitle: string;
    id: string;
    expenseAmount: string;
    currencySymbol: string;
    item: ExpenseAndAmountObject;
    expenseAndAmountList: Array<ExpenseAndAmountObject>;
    setExpenseAndAmountList: (value: Array<ExpenseAndAmountObject>) => void;
  

const ExpensesListItem: React.FC<Props> = (
    
        expenseTitle,
        id, 
        expenseAmount,
        currencySymbol,
        item,
        expenseAndAmountList,
        setExpenseAndAmountList
    : Props) => 

    const DeleteListItem = () => 
        setExpenseAndAmountList(expenseAndAmountList.filter(el => el._id !== item._id));

        axios.delete('http://localhost:4000/app/expenseslist')
        .catch(function (error) 
            console.log(error);
        );
    

    return (
        <>
            <ListItem className="list-item">
                <ListItemText primary=expenseTitle secondary=expenseAmount + currencySymbol />
                <ListItemSecondaryAction>
                    <IconButton onClick=DeleteListItem edge="end">
                        <DeleteIcon className="delete-btn" />
                    </IconButton>
                </ListItemSecondaryAction>
            </ListItem>
        </>
      );
  
  
export default ExpensesListItem;

ExpenseAndAmountObject.tsx

export interface ExpenseAndAmountObject 
    _id: string,
    expenseTitle: string,
    expenseAmount: string,

如何重新渲染列表组件?谢谢!

【问题讨论】:

【参考方案1】:

我认为问题在于异步请求。一开始我不明白你为什么要删除totalexpensesamount。但是您应该像最后那样使用异步等待按顺序执行请求。 等到删除操作完成,然后进行post请求,完成后,获取新的和更新的对象

您应该在浏览器开发者工具的网络选项卡上检查您的请求和响应。您可以轻松了解问题的根源。 可能您在数据库更新之前调用了一个 get 请求

【讨论】:

expenseslist 使用异步等待对我有用,谢谢!关于totalexpensesamount 的删除,我将其删除,因为我希望在 MongoDB 中只有一个 totalexpensesamount 值(而不是它们的列表)。也许有更好的方法来实现它,这是我第一个使用数据库的项目 也许你可以采取不同的方法。总费用可以很快改变。我认为将这些数据放在 db 上是一个坏主意,因为它依赖于另一个数据。如果你有后端,你可以在后端计算这个。只需将您的主要对象存储在数据库中。如果调用了 getTotalExpenses 服务,则获取所需的所有费用并计算 BE 端的总费用,然后返回响应

以上是关于在 React 应用程序中添加项目时,项目列表未更新的主要内容,如果未能解决你的问题,请参考以下文章

项目输出类型未更改为控制台应用程序,控制台窗口未在 WinForms 中显示

在 React Native 中动态添加项目到 FlatList

添加新项目时如何使用无限滚动更新项目列表

React 将项目添加到列表中

当在 ReactJs React-Redux 中仅创建或更新列表中的一个项目时,如何停止重新渲染整个项目列表?

React Native ListView:前置项目