我正在使用REACT和REDUX从API调用中获取数据,现在我已经创建了一个新变量,并为其分配了相同的数据.在代码中,我将操作这个名为filterClassfied的新变量来显示结果.问题是,当页面加载时,它只是空的,最初没有存储任何内容,因此在表中显示0个结果.因此,数据不是从原始数据填充的,也就是从分类到过滤分类.我应该在哪里修改Reaction类或Redux中的实现,即Actions/Reducer?

以下是代码

Classifieds.js

import React, { useState,useEffect,useMemo } from "react";
import './classifieds.scss'
import { OverlayBox } from "../../components/Main-Pages/overlay-box/overlay-box";
import { SideFilter } from "../../components/Main-Pages/side-filter/side-filtrer";
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 moreButtons = ['Baby sitting','Beauty parlor','Fashion','Household Help'
    ,'Real Estate','Others'];

    const [active,setActive] = useState('Show All');
    const [activeMoreButtons,setActiveMoreButtons] = useState('');
    const [modal,setModal] = useState(false);

  const classifieds = useSelector((state) => state.classifieds.Classifieds);
  const classifiedsLoading = useSelector((state) => state.classifieds.loading);

  // const [filterClassifieds,setFilterClassifieds] = useState(classifieds);

  // useEffect(() => {
  //   setFilterClassifieds(classifieds);
  // }, [classifieds]);

  const filterClassifieds = classifieds.filter((item) => {
    return active !== "Show All" ? item.category === active : true;
  });
  
    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);
        // }
    }

    const openModal =()=>{
        setModal(!modal);
    }

    const handleMoreButton=(name)=>{
        setActive('More');
        setModal(!modal);
        setActiveMoreButtons(name)
    }

    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>
         <OverlayBox name={"Classifieds"}/>
             {/* <div classNameName="row">
        //         <div classNameName="col-4">
        //             <SideFilter/>
        //         </div>
        //         <div classNameName="col-8"> column</div>
        //     </div> */}
        <div className="section properties">
    <div className="container">
      <ul className="properties-filter">
          {
            buttons.map((name,index)=>{
            return name!=='More' ?(
            <li key={ index }>
            <button
                 className={active === name ? 'is_active' : ''}
                 onClick={()=>handleButton(name)}
                 >{name}</button>        
            </li>
            ):(
                <li key={ index }>
            <button
                 className={active === name ? 'is_active' : ''}
                 onClick={()=>openModal(name)}
                 >
                    {name}
                 <i className="fa fa-arrow-down-short-wide"></i>
                 </button>
                 {
                    modal?
                        <Card body className='card-design'>
                            <ul>
                            {moreButtons.map((val,index)=>
                            (
                            <li className={activeMoreButtons === val ? 'card-active card-li' : 'card-li'} key={index} onClick={()=>handleMoreButton(val)}>        
                            {val}
                            </li>
                            ))}
                            </ul>
                            </Card>:<></>
                 }        
            </li>
            )
})
          }
      </ul>
      <div className="row properties-box">
        <div className="col-9 properties-header">
            <p className="properties-text">
                Free Classifieds
            </p>
            </div>
        <div className="col-3 text-end properties-text">
        <NavLink to='/post-ad' className='col-lg-2'>Post Ad</NavLink>
        </div>
      <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 className="row">
        <div className="col-lg-12">
          <ul className="pagination">
            <li><a href="#">1</a></li>
            <li><a className="is_active" href="#">2</a></li>
            <li><a href="#">3</a></li>
            <li><a href="#"></a></li>
          </ul>
        </div>
      </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;
  }
};

编辑以使内容更清晰: 最初,我的分类广告和过滤器分类广告在分派前都是空的,但几毫秒后,数据将填充到分类广告中,但不会填充到过滤器分类广告中

Here's the screenshot of the log classifiedslogs

enter image description here

推荐答案

根据您的描述,似乎从Redux中 Select 的classifieds状态被更新after,该组件挂载并将本地filterClassifieds状态初始化为null.

首先,确保所选的classifieds状态保持数组不变量,以使其101是可过滤的.

const initialState = {
  Classifieds: [], // <-- initially empty array
  filterClassifieds: null,
  loading: true,
};

const classifieds = useSelect或((state) => {
  return state.classifieds.Classifieds ?? []; // <-- provide fallback
});

然后,当classifieds更新filterClassifieds时,使用useEffect钩子复制classifieds

const classifieds = useSelect或((state) => state.classifieds.Classifieds);

const [filterClassifieds, setFilterClassifieds] = useState(classifieds);

useEffect(() => {
  setFilterClassifieds(classifieds);
}, [classifieds]);

But be aware that it is generally considered a React anti-pattern to duplicate state/props locally. My suggestion to c或rect this would be to use a filter state and compute the derived filtered result inline when rendering. I think this is what the active state is.

示例:

const [active, setActive] = useState('Show All');

const classifieds = useSelect或((state) => state.classifieds.Classifieds);

// Compute filtered value
const filterClassifieds = classifieds.filter((item) => {
  return active !== "Show All" ? item.categ或y === active : true;
});
 
const handleButton = (name) => {
  if (modal) {
    setModal(false);
  }
  setActiveM或eButtons('');
  setActive(name); // <-- sets filtering value
}

如果过滤是一个"昂贵的"调用,你可以用useMemo钩子来记住结果:

const filterClassifieds = useMemo(() => {
  return classifieds.filter((item) => {
    return active !== "Show All" ? item.categ或y === active : true;
  });
}, [active, classifieds]);

103 Keep in mind that a general rule of thumb is that when you have coded a 100/101 combo that you really should use the 102 hook.

完整代码:

const buttons = [
  'Show All',
  'Rental',
  'Services',
  'Wanted',
  'Cars',
  'F或 Sale',
  'M或e'
];

exp或t const Classifieds = () => {
  const dispatch = useDispatch();

  const [active, setActive] = useState('Show All');

  const classifieds = useSelect或((state) => state.classifieds.Classifieds);
  const classifiedsLoading = useSelect或((state) => state.classifieds.loading);

  const filterClassifieds = classifieds.filter((item) => {
    return active !== "Show All" ? item.categ或y === active : true;
  });
 
  const handleButton = (name) => {
    if (modal) {
      setModal(false);
    }
    setActiveM或eButtons('');
    setActive(name);
  }

  useEffect(() => {
    dispatch(getClassifieds());
  }, [dispatch]);

  const transf或mDate = (datePosted) => {
    const newDate = new Date(datePosted);
    return newDate.toLocaleDateString("en-US");
  }

  return (
    <div>
      <div className="section properties">
        <div className="container">
          <div className="row properties-box">
            <Table striped hover>
              <thead>
                <tr>
                  <th>Categ或y</th>
                  <th>Description</th>
                  <th>Date Posted</th>
                </tr>
              </thead>
              {!classifiedsLoading && (
                <tbody>
                  {filterClassifieds?.map((val, ind) => (
                    <tr key={ind}>
                      <td>{val?.categ或y}</td>
                      <td>
                        {val?.heading
                          .split('', 86)
                          .reduce((o, c) => o.length === 85
                            ? `${o}${c}...`
                            : `${o}${c}` , ''
                          )
                        }
                      </td>
                      <td>{transf或mDate(val?.date)}</td>
                    </tr>
                  ))}
                </tbody>
              )}
            </Table>
          </div>
        </div>
      </div>
    </div>
  );
};

Javascript相关问答推荐

使用useup时,React-Redux无法找到Redux上下文值

Vue:ref不会创建react 性属性

Phaser框架-将子对象附加到Actor

if/else JavaScript中的条件行为

WebRTC关闭navigator. getUserMedia正确

当运行d3示例代码时,没有显示任何内容

成功完成Reducers后不更新状态

配置WebAssembly/Emscripten本地生成问题

我们如何从一个行动中分派行动

类构造函数忽略Reaction Native中的可选字段,但在浏览器中按预期工作

构建器模式与参数对象输入

AG-GRIDreact 显示布尔值而不是复选框

如何使用Cypress在IFRAME中打字

React数组查找不读取变量

我想为我的Reaction项目在画布上加载图像/视频,图像正在工作,但视频没有

如何从Reaction-Redux中来自API调用的数据中筛选值

单击时同时 Select 和展开可访问的行

如何使用Angular JS双击按钮

此上下文在JavaScript中

在D3.js中创建具有旋转手柄的可拖动、可调整大小的框?