删除模态。反应终极版。无法读取未定义的 属性“_id”
Delete Modal. React Redux. Cannot read property '_id' of undefined
正在尝试删除费用跟踪器的交易。当用户单击垃圾桶图标时,应出现一个模式。相反,无法读取 属性 未定义的 '_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
直接由路由呈现,因此从作为 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 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>
正在尝试删除费用跟踪器的交易。当用户单击垃圾桶图标时,应出现一个模式。相反,无法读取 属性 未定义的 '_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
直接由路由呈现,因此从作为 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 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>