javascript - 将 Hooks 与 Redux 一起使用——不好的做法?
问题描述
我正在尝试实现一个排序表,如 Semantic UI Docs 中所示。
https://react.semantic-ui.com/collections/table/#variations-sortable
我在我的项目中使用 redux,并且对如何实现排序表和搜索输入功能感到困惑。
在页面加载时,我将所有数据存储在称为棒球的状态中。我还有一个 cardsToShow 状态,如果用户正在搜索某些东西,它会更新,由 searchCards 函数触发。cardToShow 状态是我用来显示我的数据的状态。
const mapStateToProps = state => {
return {
baseball: state.baseball,
cardsToShow: searchCards(state)
};
};
const searchCards = ({ baseball, search }) => {
return search
? baseball.filter(a =>
a.title[0].toLowerCase().includes(search.toLowerCase())
)
: baseball;
};
在 Semantic UI/Lodash 示例中,它们会在用户单击列时更新和排序数据状态。
我尝试使用列、方向和过滤数据字段的一些状态挂钩来复制它。
const Cards = props => {
const [column, setColumn] = useState(null);
const [direction, setDirection] = useState(null);
const [filteredData, setData] = useState(props.cardsToShow);
const handleSort = clickedColumn => {
if (column !== clickedColumn) {
setColumn(clickedColumn);
setData(_.sortBy(filteredData, [clickedColumn]));
setDirection("ascending");
return;
}
setData(_.sortBy(filteredData.reverse()));
direction === "ascending"
? setDirection("descending")
: setDirection("ascending");
};
这也是我的列标题的样子:
<Table.HeaderCell
sorted={column === "title" ? direction : null}
onClick={handleSort("title")}
>
Card Title
</Table.HeaderCell>
首先,我在上面的代码中收到“重新渲染过多”错误,这是一个问题。但主要问题是我现在有一个正在更新的过滤数据字段......但我还有其他状态卡显示。
我知道我在这里所做的任何事情都是错误的,但很想知道是否有人对如何最好地完成这一点有任何指导。使用这样的钩子以及拥有一个保存全局状态的 redux 存储是否可以接受?或者我应该以某种方式为我想要做的排序创建另一个减速器?谢谢。
---编辑---更新了下面的组件
import React, { useState } from "react";
import Search from "./Search";
import TimeAgo from "react-timeago";
import { useSelector} from "react-redux";
import { Table } from "semantic-ui-react";
import _ from "lodash";
// import { useField } from "../hooks";
const searchCards = ({ baseball, search }) => {
return search
? baseball.filter(a =>
a.title[0].toLowerCase().includes(search.toLowerCase())
)
: baseball;
};
const Cards = () => {
const baseball = useSelector(state => state.baseball);
const search = useSelector(state => state.search);
const cardsToShow = searchCards(baseball, search);
const [column, setColumn] = useState(null);
const [direction, setDirection] = useState(null);
const [filteredData, setData] = useState(cardsToShow);
const handleSort = clickedColumn => {
if (column !== clickedColumn) {
setColumn(clickedColumn);
setData(_.sortBy(filteredData, [clickedColumn]));
setDirection("ascending");
return;
}
setData(_.sortBy(filteredData.reverse()));
direction === "ascending"
? setDirection("descending")
: setDirection("ascending");
};
return (
<>
<div>
<Search />
<h3>Vintage Card Search</h3>
<Table sortable celled fixed striped>
<Table.Header>
<Table.Row>
<Table.HeaderCell
sorted={column === "title" ? direction : null}
onClick={handleSort("title")}
>
Card Title
</Table.HeaderCell>
<Table.HeaderCell># Bids</Table.HeaderCell>
<Table.HeaderCell>Watchers</Table.HeaderCell>
<Table.HeaderCell>Price</Table.HeaderCell>
<Table.HeaderCell>Time Left</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{filteredData.map(card => (
<>
<Table.Row key={card.id}>
<Table.Cell>{card.title}</Table.Cell>
<Table.Cell>
{card.sellingStatus[0].bidCount
? card.sellingStatus[0].bidCount
: 0}
</Table.Cell>
<Table.Cell>
{card.listingInfo[0].watchCount
? card.listingInfo[0].watchCount
: 0}
</Table.Cell>
<Table.Cell>
$
{card.sellingStatus &&
card.sellingStatus[0].currentPrice[0]["__value__"]}
</Table.Cell>
<Table.Cell>
<TimeAgo
date={new Date(
card.listingInfo && card.listingInfo[0].endTime
).toLocaleDateString()}
/>
</Table.Cell>
</Table.Row>
</>
))}
</Table.Body>
</Table>
</div>
</>
);
};
export default Cards;
解决方案
而不是像以前那样使用 Redux,请以这种方式在 hooks 中尝试新的 Redux 实现:
import React, {useState} from "react";
import {useSelector } from "react-redux";
const searchCards = (baseball, search) => {
return search
? baseball.filter(a =>
a.title[0].toLowerCase().includes(search.toLowerCase())
)
: baseball;
};
export const Cards = () => {
const baseball = useSelector(state => state.baseball);
const search = useSelector(state => state.search);
const cardsToShow = searchCards(baseball, search);
const [column, setColumn] = useState(null);
const [direction, setDirection] = useState(null);
const [filteredData, setData] = useState(cardsToShow);
const handleSort = clickedColumn => {
if (column !== clickedColumn) {
setColumn(clickedColumn);
setData(_.sortBy(filteredData, [clickedColumn]));
setDirection("ascending");
return;
}
setData(_.sortBy(filteredData.reverse()));
direction === "ascending"
? setDirection("descending")
: setDirection("ascending");
};
return {filteredData, handleSort};
};
从你解释你想要实现的内容来看,我发现你需要导出filteredData
元素(显示已过滤和排序的棒球卡)和handleSort
能够触发Table
组件更改的方法。我认为您不需要再次将过滤和排序的元素存储在 Redux 中。reselect
如果您想这样做并提高性能,使用和记忆选择器就足够了。
推荐阅读
- azure - 如何创建变量并将其设置为等于特定 customEvent 的计数?
- google-sheets - 如何将主题和内容拆分为多行?
- python - 当 python 2x 是您的默认 python 版本但您在 Bash 上使用 python 3x 时,如何在 pip 上安装 Django 2x
- database - 用 laravel 连接多个数据库
- php - 使用utf 8从android发送html post json数组到php并输入到数据库?
- c++ - 向量
> 运营商 - opencv - 用彩色线条隔离帧的参数
- python - 如何替换整数和字符串的特定组合?
- python - 使用 pd.read_excel() 时如何更新工作簿链接?
- jestjs - 如何停止 Jest 在测试输出中包装“console.log”?