删除模态。反应 Redux。无法读取未定义的属性“_id”

Posted

技术标签:

【中文标题】删除模态。反应 Redux。无法读取未定义的属性“_id”【英文标题】:Delete Modal. React Redux. Cannot read property '_id' of undefined 【发布时间】:2021-10-07 12:01:59 【问题描述】:

尝试删除费用跟踪器的交易。当用户点击垃圾桶图标时,应该会出现一个模式。相反,无法读取未定义的属性“_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;

app.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);

【问题讨论】:

什么是渲染DeleteTransactionModal 并将道具传递给它?该错误似乎暗示 transaction 属性未定义。 所以我认为DeleteTransactionModal 是由Route 渲染的,其路径类似于"/transactions/delete/:id"?是的,您可以访问路由参数并提取交易 ID。如果DeleteTransactionModal 没有在路由上渲染,而是由另一个组件渲染,则需要传递所有的props。 是的,这正是它的路由方式。我刚刚再次更新了帖子。如果不使用 this 关键字,您将如何提取交易 ID? 不确定this 来自哪里,但this 在函数组件中只是未定义。不过,我确实在下面提供了有关如何访问路由参数的答案。 好的,所以我用你的建议更新了模态,如上所示。但是,我现在在 URL 中获取事务/删除/未定义,而不是 ID 号。 【参考方案1】:

由于DeleteTransactionModal是由路由直接渲染的,所以从作为props传递的route props访问事务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 挂钩。

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>

【讨论】:

以上是关于删除模态。反应 Redux。无法读取未定义的属性“_id”的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:无法读取未定义反应redux的属性“历史”[重复]

反应笑话单元测试用例TypeError:无法读取未定义的属性'then'

React Redux TypeError:无法读取未定义的属性“地图”

无法读取未定义单元测试酶的属性“contextTypes”

下一个 redux 包装器出现无法读取未定义的属性 'getState' 的错误

无法读取未定义的属性“类型”(react-router-redux)