reactjs - 删除模态。反应 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);
解决方案
由于是直接由路由渲染的,所以从作为 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>
推荐阅读
- mocking - 模拟设置不返回预期值
- python - 有没有更好的方法来使用烧瓶的滚动条错误报告?
- javascript - JQuery ':contains' 将其转换为 Javascript
- apache-spark - 如何在 scala/pyspark 中对 xgboost 使用单调约束
- ios - iOS 作为 BLE 外设和中央模式问题
- angular - @ViewChild 在不是第一个选项卡时在 mat-tab 中未定义
- mysql - 在存储过程中使用游标
- c++ - 如何从 dart 异步调用用 C/C++ 编写的函数?
- sql - postgres - 在同一列上删除多个表(在每个表中)
- javascript - react-datepicker 组件中的未知单词错误