首页 > 解决方案 > 在 React 应用程序中添加项目时,项目列表未更新

问题描述

我使用 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;

费用清单项目.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;

费用和金额对象.tsx

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

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

标签: javascriptreactjsmongodbaxiosuse-effect

解决方案


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

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


推荐阅读