reactjs - 来自 useSelector 的数据导致无限重新渲染为依赖项
问题描述
我正在使用 redux-thunk 做一个简单的 CRUD。
一切正常,我从 store 获取数据,就像这样,我将它呈现在一个表组件中。
表格组件摘录
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { getItems } from '../actions/actions'
import ButtonCreate from '../components/buttons/ButtonCreate'
import ButtonDelete from '../components/buttons/ButtonDelete'
import ButtonUpdate from '../components/buttons/ButtonUpdate'
export const Table = () => {
const dispatch = useDispatch()
const { data } = useSelector(state => state.axiosDataReducer)
console.log(data)
useEffect(() => {
dispatch(getItems())
}, [dispatch])
return (
<div className='container mt-5 mb-5'>
<ButtonCreate />
<table className="table table-striped table-hover caption-top ">
<caption>Online Store</caption>
<thead className='table-dark'>
<tr className='text-center'>
<th scope="col">Id</th>
<th scope="col">Name</th>
<th scope="col">Cost</th>
<th scope="col">Category</th>
<th scope="col">Department</th>
<th scope="col">Update</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
{
data?.map((x, index) => (
<tr key={x.id}>
<th scope="col">{index + 1}</th>
<th scope="col">{x.name}</th>
<th scope="col">$ {x.cost?.toFixed(2)}</th>
<th className='text-center'>
{
x.category.map((y, index) => (
<span key={index * 0.125}>{y.name}</span>
))
}
</th>
<th className='text-center'>
{
x.department.map((z, index) => (
<span key={index * 0.225}>{z.name}</span>
))
}
</th>
<th><ButtonUpdate id={x.id} /></th>
<th><ButtonDelete id={x.id} /></th>
</tr>
))
}
</tbody>
</table>
</div>
)
}
这是运行中的 fetchdata 函数:
// get items
export const getItems = () => {
return async (dispatch) => {
try {
const response = await axios.get(baseURL);
const data = response.data;
dispatch({
type: types.get,
data: data
});
} catch (error) {
return dispatch(
{
type: types.error,
msg: "Unable to get items"
});
}
};
};
但是,当我删除一项时,我希望 Table 组件重新渲染一次,以显示缺少已删除值的新表。因此,当我使用数据配置 useEffect 时,它会无限重新渲染。
useEffect(() => {
dispatch(getItems())
}, [dispatch,data])
我只想让组件渲染一次导致数据的长度发生变化,但它没有做任何事情(data?.length),显示新的表格
我怎样才能避免这种情况?当然,我可以使用某种页面重新加载,但似乎这不是解决方案。
我已经阅读了有关 memo、useMemo 和 useCallback 的信息,但我不知道在这种情况下如何配置它。
我正在添加减速器:
import { types } from "../types/types";
const initialState = {
data: null,
selected: null,
deleted: '',
created: null,
modified: null,
error: ''
}
export const axiosDataReducer = (state = initialState, action) => {
switch (action.type) {
case types.get:
return {
...state,
data: action.data
}
case types.selected:
return {
...state,
selected: action.selectedItem
}
case types.delete:
return {
...state,
deleted: action.deletedItem
}
case types.created:
return {
...state,
created: action.createdItem
}
case types.modified:
return {
...state,
modified: action.modifiedItem
}
case types.error:
return {
...state,
error: action.msg
}
default:
return state;
}
}
以及删除操作:
//delete item
export const selectItem = (id) => {
return async (dispatch) => {
try {
const response = await axios.get(`${baseURL}${id}`);
const data = response.data;
dispatch({
type: types.selected,
selectedItem: data
});
} catch (error) {
return dispatch(
{
type: types.error,
msg: "Unable to select item for delete"
});
}
};
}
const sweetAlertConfirmDeleteItem = (id, dispatch) => {
Swal.fire({
title: 'Are you sure?',
text: "You won't be able to revert this!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((result) => {
if (result.isConfirmed) {
axios.delete(`${baseURL}${id}`);
dispatch({
type: types.delete,
deletedItem: 'Item deleted'
})
Swal.fire(
'Deleted!',
'Your file has been deleted.',
'success'
)
}
})
}
export const getItemDeleteGetItems = (id) => {
return async (dispatch) => {
try {
dispatch(selectItem(id))
sweetAlertConfirmDeleteItem(id, dispatch)
} catch (error) {
return dispatch(
{
type: types.error,
msg: "Unable to delete item"
});
}
};
};
解决方案
在您sweetAlertConfirmDeleteItem
发送删除操作时,像这样发送它,
dispatch({
type: types.delete,
deletedItem: { id }
})
现在在你的 reducer 中你可以做到这一点,一旦你得到了被删除的项目,就将它从数据中删除。
case types.delete:
return {
...state,
data: state.data.filter(item => item.id !== action.deletedItem.id),
deleted: action.deletedItem
}
还要从 useEffect 中删除data
作为依赖项。
推荐阅读
- javascript - NodeJs Array.join 在数组的每个部分上都有文本
- python - 当您最终需要一个列表时,Python 生成器的内存节省功能
- python - Django 错误:“ModuleNotFoundError:没有名为‘classroom’的模块”
- c# - 如何拦截 DbContext 中的 ModelBuilder 实例?
- reactjs - Lighthouse 认为打字机动画是布局转变
- c# - Unity、C#、2D:如何将 UI 画布项(按钮)位置设置为与另一个游戏对象相同的位置?
- wordpress - 将可变产品价格范围替换为“来自:”+ WooCommerce 中使用 number_format 的最低价格
- java - Java接口和信息输出到控制台的问题
- python - 如何使用烧瓶在 html 中显示相同的缩进 json 内容
- spring-boot - Springboot GraphQL:错误的获取请求:路径不是模式'/json'