我正在使用 React 和 Redux 从 API 调用中获取数据,现在我创建了一个新变量并为其分配了相同的数据。在代码中,我将操作这个名为 filterClassifieds 的新变量来显示结果。问题是,当页面加载时,它只是空的,并且最初不存储任何内容,因此在表中显示 0 个结果。因此,数据不是从原始数据(即分类数据)填充到过滤器分类数据。我应该在哪里修改我的 React 类或 Redux 中的实现,即 actions/reducers?
这是代码
classifieds.js
import React, { useState,useEffect } from "react";
import './classifieds.scss'
import Table from 'react-bootstrap/Table';
import { NavLink } from 'react-router-dom';
import Card from 'react-bootstrap/Card';
import { useDispatch, useSelector } from 'react-redux';
import SpinnerButton from "../../components/Spinner/Spinner";
import { getClassifieds } from "../../redux/actions/classifiedsAction";
export const Classifieds = ()=>{
const dispatch = useDispatch();
const buttons = ['Show All','Rental','Services','Wanted','Cars','For Sale', 'More'];
const [active,setActive] = useState('Show All');
const classifieds = useSelector((state) => state.classifieds.Classifieds);
const classifiedsLoading = useSelector((state) => state.classifieds.loading);
const [filterClassifieds,setFilterClassifieds] = useState(classifieds);
const handleButton = (name)=>{
if(modal)setModal(false);
setActiveMoreButtons('');
setActive(name);
if(name==='Show All'){
setFilterClassifieds(classifieds);
}else{
let newClassifieds = classifieds.filter((itm)=>
{
return itm.category === name;
}
)
setFilterClassifieds(newClassifieds);
}
}
useEffect(() => {
const generateClassifieds = async () => {
await dispatch(getClassifieds());
};
generateClassifieds();
}, [dispatch]);
const transformDate = (datePosted)=> {
let newDate = new Date(datePosted);
return newDate.toLocaleDateString("en-US");
}
// console.log(filterClassifieds);
return(
<div>
<div className="section properties">
<div className="container">
<div className="row properties-box">
<Table striped hover>
<thead>
<tr>
<th>Category</th>
<th>Description</th>
<th>Date Posted</th>
</tr>
</thead>
{classifiedsLoading?<></>:
<tbody>
{filterClassifieds?.map((val,ind)=>(
<tr key={ind}>
<td>{val?.category}</td>
<td>{val?.heading.split('', 86).reduce((o, c) => o.length === 85 ? `${o}${c}...` : `${o}${c}` , '')}</td>
<td>{transformDate(val?.date)}</td>
</tr>
))}
</tbody>
}
</Table>
</div>
</div>
</div>
</div>
)
}
action.js
import axios from "axios";
export const GET_CLASSIFIEDS = "GET_CLASSIFIEDS";
export const CLASSIFIEDS_LOADING = "CLASSIFIEDS_LOADING";
// Get all posts
export const getClassifieds = () => (dispatch) => {
dispatch(setClassifiedsLoading());
axios
.get("/posts")
.then((res) =>
dispatch({
type: GET_CLASSIFIEDS,
payload: res.data,
})
)
.catch((err) =>
dispatch({
type: CLASSIFIEDS_LOADING,
payload: {},
})
);
};
// Classifieds loading
export const setClassifiedsLoading = () => {
return {
type: CLASSIFIEDS_LOADING,
};
};
reducer.js
import { GET_CLASSIFIEDS, CLASSIFIEDS_LOADING } from "../actions/classifiedsAction";
const initialState = {
Classifieds: null,
filterClassifieds: null,
loading: true,
};
export const ClassifiedsReducer = (state = initialState, action) => {
switch (action.type) {
case GET_CLASSIFIEDS:
return {
...state,
Classifieds: action.payload,
loading: false,
};
case CLASSIFIEDS_LOADING:
return {
...state,
loading: true,
};
default:
return state;
}
};
根据您的描述,似乎从 Redux 中选择的
classifieds
状态已更新 after 该组件安装并将本地 filterClassifieds
状态初始化为 null
。
您可以使用
useEffect
钩子在更新时复制 classifieds
filterClassifieds
const classifieds = useSelector((state) => state.classifieds.Classifieds);
const [filterClassifieds, setFilterClassifieds] = useState(classifieds);
useEffect(() => {
setFilterClassifieds(classifieds);
}, [classifieds]);
但请注意,在本地复制状态/属性通常被认为是 React 反模式。我纠正这个问题的建议是使用过滤器状态并在渲染时内联计算派生的过滤结果。我想这就是
active
状态。
示例:
const [active, setActive] = useState('Show All');
const classifieds = useSelector((state) => state.classifieds.Classifieds);
// Compute filtered value
const filterClassifieds = classifieds.filter((item) => {
return active !== "Show All" ? item.category === name : true;
});
const handleButton = (name) => {
if (modal) {
setModal(false);
}
setActiveMoreButtons('');
setActive(name); // <-- sets filtering value
}
如果过滤是一个“昂贵”的调用,您可以使用
useMemo
钩子记住结果:
const filterClassifieds = useMemo(() => {
return classifieds.filter((item) => {
return active !== "Show All" ? item.category === name : true;
});
}, [active, classifieds]);
完整代码:
const buttons = [
'Show All',
'Rental',
'Services',
'Wanted',
'Cars',
'For Sale',
'More'
];
export const Classifieds = () => {
const dispatch = useDispatch();
const [active, setActive] = useState('Show All');
const classifieds = useSelector((state) => state.classifieds.Classifieds);
const classifiedsLoading = useSelector((state) => state.classifieds.loading);
const filterClassifieds = classifieds.filter((item) => {
return active !== "Show All" ? item.category === name : true;
});
const handleButton = (name) => {
if (modal) {
setModal(false);
}
setActiveMoreButtons('');
setActive(name);
}
useEffect(() => {
dispatch(getClassifieds());
}, [dispatch]);
const transformDate = (datePosted)=> {
const newDate = new Date(datePosted);
return newDate.toLocaleDateString("en-US");
}
// console.log(filterClassifieds);
return (
<div>
<div className="section properties">
<div className="container">
<div className="row properties-box">
<Table striped hover>
<thead>
<tr>
<th>Category</th>
<th>Description</th>
<th>Date Posted</th>
</tr>
</thead>
{!classifiedsLoading && (
<tbody>
{filterClassifieds?.map((val, ind) => (
<tr key={ind}>
<td>{val?.category}</td>
<td>
{val?.heading
.split('', 86)
.reduce((o, c) => o.length === 85
? `${o}${c}...`
: `${o}${c}` , ''
)
}
</td>
<td>{transformDate(val?.date)}</td>
</tr>
))}
</tbody>
)}
</Table>
</div>
</div>
</div>
</div>
);
};