首页 > 解决方案 > 删除模态。反应 Redux。无法读取未定义的属性“_id”

问题描述

尝试删除费用跟踪器的交易。当用户点击垃圾桶图标时,应该会出现一个模式。相反,无法读取未定义的属性“_id”。

我猜我需要一个带有 match.params 的 useEffect 钩子?还是我需要在模式上再次列出交易?

数据

 const transactions = [
  {
    name: "Rent",
    href: "#",
    category: "expense",
    amount: "-1000",
    currency: "USD",
    status: "processing",
    date: "July 1, 2020",
    datetime: "2020-07-11",
  },
  {
    name: "Google",
    href: "#",
    category: "income",
    amount: 5000,
    currency: "USD",
    status: "success",
    date: "July 18, 2020",
    datetime: "2020-07-18",
  },
  {
    name: "Facebook",
    href: "#",
    category: "income",
    amount: "15000",
    currency: "USD",
    status: "success",
    date: "July 18, 2020",
    datetime: "2020-07-18",
  },
  {
    name: "Payment to Molly Sanders",
    href: "#",
    category: "expense",
    amount: "-2000",
    currency: "USD",
    status: "success",
    date: "July 11, 2020",
    datetime: "2020-07-11",
  },
];

export default transactions;

应用程序.js

 function App() {


return (
    <Router history={history}>
      <Route path='/' exact component={DashboardScreen} />
      <Route path='/transaction/add' exact component={AddTransactionModal} />
      <Route
        path='/transactions/delete/:id'
        exact
        component={DeleteTransactionModal}
      />
    </Router>
  );
}

交易清单:

import React, { useEffect } from "react";
import { Link } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";

const TransactionList = () => {
    const dispatch = useDispatch();
  
    const transactionList = useSelector((state) => state.transactionList);
    const { loading, error, transactions } = transactionList;
  
    useEffect(() => {
      dispatch(listTransactions());
    }, [dispatch]);
  
  
    return (
      <div className=''>
        <h2 className=''>
          Recent activity
        </h2>
      
        <div className=''>
          <nav
            className=''
            aria-label='Pagination'>
            <div className='f'>
              <a
                href='#'
                className=''>
                Previous
              </a>
              <a
                href='#'
                className=''>
                Next
              </a>
            </div>
          </nav>
        </div>
  
       
              <div className=''>
                <table className=''>
                  <thead>
                    <tr>
                      <th className=''>
                        Transaction
                      </th>
                      <th className=''>
                        Amount
                      </th>
                      <th className=''>
                        Action
                      </th>
                      <th className=''>
                        Date
                      </th>
                    </tr>
                  </thead>
                  <tbody className=''>
                    {transactions.map((transaction) => (
                      <tr key={transaction.id} className=''>
                        <td className=''>
                          <div
                            className="">
                            <a
                              href={transaction.href}
                              className=''>
                              <CashIcon
                                className=''
                                aria-hidden='true'
                              />
                              <p className=''>
                                {transaction.name}
                              </p>
                            </a>
                          </div>
                        </td>
                        <td className=''>
                          <span className=''>
                            {numberWithCommas(transaction.amount)}{" "}
                          </span>
                          {transaction.currency}
                        </td>
                        <td className=''>
                          <span className=' '>
                            <Link to={`/transactions/delete/${transaction.id}`}>
                              <TrashIcon
                                className=''
                                aria-hidden='true'
                              />{" "}
                            </Link>
                            <Link>
                              <PencilAltIcon
                                className=''
                                aria-hidden='true'
                              />
                            </Link>
                          </span>
                        </td>
  
                        <td className=''>
                          <time dateTime={transaction.datetime}>
                            {transaction.date}
                          </time>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>
   
    );
  };
  
  export default TransactionList;



 

删除交易模式:

import React from "react";
import { useRef, useState, useEffect } from "react";


import { useParams } from "react-router-dom";
import { connect, useDispatch, useSelector } from "react-redux";
import { Redirect, Link } from "react-router-dom";
import {
  deleteTransaction,

} from "../../actions/transactionActions";

import DashboardScreen from "../../screens/DashboardScreen";
import StandardModal from "./StandardModal";

const DeleteTransactionModal = () => {
  const dispatch = useDispatch();
  const { id } = useParams();
  const [open, setOpen] = useState(true);
  const cancelButtonRef = useRef(null);


  if (!open) {
    return <Redirect to='/' />;
  }

  const actions = (
    <React.Fragment>
      <button
        type='button'
        onClick={() => dispatch(deleteTransaction(id))}
        className=''>
        Delete
      </button>
      <Link
        to='/'
        type='button'
        className=''
        onClick={() => setOpen(false)}
        ref={cancelButtonRef}>
        Cancel
      </Link>
    </React.Fragment>
  );

  return (
    <div>
      <DashboardScreen />
      console.log(transaction.id)
      <StandardModal
        title='Delete Transaction'
        content='Are you sure you want to delete this transaction?'
        actions={actions}
      />
    </div>
  );
};

export default connect(null, { deleteTransaction })(DeleteTransactionModal);

标签: reactjsreduxreact-hooksmodal-dialogreact-router-dom

解决方案


由于是直接由路由渲染的,所以从作为 props 传递的路由 propsDeleteTransactionModal访问事务。id

const DeleteTransactionModal = ({
  deleteTransaction,
  match, // <-- destructure the match prop
}) => {
  const { id } = match.params; // <-- access the id param

  const actions = (
    <React.Fragment>
      <button
        type='button'
        onClick={() => deleteTransaction(id)} // <-- pass id to action
        className='modal-css'
      >
        Delete
      </button>
      <Link
        to='/'
        type='button'
        className='modal-css'
        onClick={() => setOpen(false)}
        ref={cancelButtonRef}
      >
        Cancel
      </Link>
    </React.Fragment>
  );


  return (
    <div>
      <DashboardScreen />
      <StandardModal
        title='Delete Transaction'
        content='Are you sure you want to delete this transaction?'
        actions={actions}
      />
    </div>
  );
}

export default connect(null, { deleteTransaction })(
  DeleteTransactionModal
);

connect我建议使用HOC转换为 React hooks 。

import { useDispatch } from 'react-redux';
import { useParams } from 'react-router-dom';

const DeleteTransactionModal = () => {
  const dispatch = useDispatch();
  const { id } = useParams();

  const actions = (
    <React.Fragment>
      <button
        type='button'
        onClick={() => dispatch(deleteTransaction(id))}
        className='modal-css'
      >
        Delete
      </button>
      <Link
        to='/'
        type='button'
        className='modal-css'
        onClick={() => setOpen(false)}
        ref={cancelButtonRef}
      >
        Cancel
      </Link>
    </React.Fragment>
  );


  return (
    <div>
      <DashboardScreen />
      <StandardModal
        title='Delete Transaction'
        content='Are you sure you want to delete this transaction?'
        actions={actions}
      />
    </div>
  );
}

路线优化建议

由于您似乎一次只想渲染一个路由,因此将它们渲染到一个Switch组件中,并将路由从最具体的路径重新排序到最不具体的路径。这允许您删除exact道具。

<Router history={history}>
  <Switch>
    <Route path='/transactions/delete/:id' component={DeleteTransactionModal} />
    <Route path='/transaction/add' component={AddTransactionModal} />
    <Route path='/' component={DashboardScreen} />
  </Switch>
</Router>

推荐阅读