reactjs Redux Store不会在React组件中触发重新渲染

mv1qrgav  于 12个月前  发布在  React
关注(0)|答案(2)|浏览(128)

我在使用Redux商店时遇到了React组件中重新渲染的问题。我使用的是功能组件。
这是我的App.js,应该重新渲染

import Habbit from "./Habbit";
import NavBar from "./NavBar";
import HabitTrackerWeekView from "./HabitTrackerWeekView";
import { switchComponents, addHabit } from "../Action";
import { useEffect, useState } from "react";

function App({ store }) {
  const [newHabit, setNewHabit] = useState("");
  const { habitList, switchCom, currentMonth, doneCount } = store.getState();
  useEffect(() => {
    console.log("app.js done count ", doneCount);
  }, [doneCount]);

  return (
    <div className="App">
      <NavBar />
      <HabitTrackerWeekView
        habits={store.getState()}
        dispatch={store.dispatch}
        currentMonth={currentMonth}
      />
    </div>
  );
}

export default App;

字符串
这是我的日志TrackerWeekView.js,其中doneCount发送到Redux商店

import React, { useEffect, useReducer, useState } from "react";
import { countDoneStatuses } from "../Action";
import {
  format,
  subWeeks,
  startOfWeek,
  endOfWeek,
  eachDayOfInterval,
  addWeeks,
} from "date-fns";

function HabitTrackerWeekView({ habits, dispatch }) {
  const { habitList } = habits;
  const [currentMonth, setCurrentMonth] = useState(new Date());
  const [habitStatuses, setHabitStatuses] = useState({});
  const [habitDoneCounts, setHabitDoneCounts] = useState(
    habitList.reduce((counts, habit) => ({ ...counts, [habit]: 0 }), {})
  );
  useEffect(() => {
    // console.log("Current habitDoneCounts:", habitDoneCounts);
    dispatch(countDoneStatuses(habitDoneCounts));
  }, [habitDoneCounts]);

  const weekdays = [
    "Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
  ];
  const getCurrentWeekDates = () => {
    const startOfCurrentWeek = startOfWeek(currentMonth, { weekStartsOn: 1 });
    const endOfCurrentWeek = endOfWeek(currentMonth, { weekStartsOn: 1 });
    const datesOfCurrentWeek = eachDayOfInterval({
      start: startOfCurrentWeek,
      end: endOfCurrentWeek,
    });
    const formattedDatesOfCurrentWeek = datesOfCurrentWeek.map((date) =>
      format(date, "dd")
    );

    return formattedDatesOfCurrentWeek;
  };
  const dates = getCurrentWeekDates();
  const handlePreviousWeek = () => {
    setCurrentMonth(subWeeks(currentMonth, 1));
  };

  const getMonthYear = () => {
    const dateFormat = "MMM yyyy";
    return format(currentMonth, dateFormat);
  };

  const handleNextWeek = () => {
    setCurrentMonth(addWeeks(currentMonth, 1));
  };

  const handleTodaysStatus = (date, habit) => {
    const key = `${date}-${habit}`;
    setHabitStatuses((prevStatuses) => {
      const currentStatus = prevStatuses[key] || "none";

      const newStatus =
        currentStatus === "none"
          ? "done"
          : currentStatus === "done"
          ? "not done"
          : "none";
      setHabitDoneCounts((prevCounts) => ({
      ...prevCounts,
      [habit]:
        newStatus === "done"
          ? prevCounts[habit] + 1
          : Math.max(0, prevCounts[habit] - 1),
    }));
      return { ...prevStatuses, [key]: newStatus };
    });
    // console.log(habitStatuses);
  };

  return (
    <div className="habit-tracker-week-view">
      <div className="months">
        <div className="previous-month" onClick={handlePreviousWeek}>
          <img
            width="24"
            height="24"
            src="https://img.icons8.com/material-outlined/24/back--v1.png"
            alt="back--v1"
          />
        </div>
        <div className="month">{getMonthYear()}</div>
        <div className="next-month" onClick={handleNextWeek}>
          <img
            width="24"
            height="24"
            src="https://img.icons8.com/material-outlined/24/forward.png"
            alt="forward"
          />
        </div>
      </div>
      <div className="day-of-the-week">
        {weekdays.map((day) => (
          <label>{day}</label>
        ))}
      </div>
      {/* <h1>Habit Tracker</h1> */}
      <div className="habits">
        {habitList.map((habit) => (
          <>
            <div className="habit-info">
              <div className="habit-name">{habit}</div>
              <div className="habit-time">time</div>
            </div>
            <div className="habit-dates">
              {dates.map((date) => (
                <div
                  className={`habit-date ${
                    habitStatuses[`${date}-${habit}`] === "done"
                      ? "done"
                      : `${
                          habitStatuses[`${date}-${habit}`] === "not done"
                            ? "not-done"
                            : ""
                        }`
                  }`}
                  onClick={() => handleTodaysStatus(date, habit)}
                >
                  {date}
                </div>
              ))}
            </div>
          </>
        ))}
      </div>
    </div>
  );
}
export default HabitTrackerWeekView;


我在redux-dev-tool上检查了一下,流是好的,它正在更新正确的状态。

2ul0zpep

2ul0zpep1#

调用store.getState()不会将React组件订阅到store,这是一个一次性的操作。使用useSelector钩子订阅store中的更改。当选定的值更改时,组件会被触发重新呈现并选择更新的状态值。
范例:

...
import { useDispatch, useSelector } from 'react-redux';
...

function App() {
  const dispatch = useDispatch();

  const habitList = useSelector(state => state.habitList);
  const switchCom = useSelector(state => state.switchCom);
  const currentMonth = useSelector(state => state.currentMonth);
  const doneCount = useSelector(state => state.doneCount);

  const [newHabit, setNewHabit] = useState("");
  
  useEffect(() => {
    console.log("app.js done count ", doneCount);
  }, [doneCount]);

  return (
    <div className="App">
      <NavBar />
      <HabitTrackerWeekView
        habits={habitList}
        dispatch={dispatch}
        currentMonth={currentMonth}
      />
    </div>
  );
}

字符串

  • 建议:HabitTrackerWeekView应该使用useSelector钩子并选择它需要的状态,而不是在父组件中选择它们并作为props传递。
function HabitTrackerWeekView() {
  const dispatch = useDispatch();

  const habitList = useSelector(state => state.habitList);
  const currentMonth = useSelector(state => state.currentMonth);
  const doneCount = useSelector(state => state.doneCount);

  ...

fxnxkyjh

fxnxkyjh2#

它只创建一个redux store,但没有reactredux连接。
您需要订阅才能将redux storereact一起使用。
订阅后,react将在redux store中的值发生变化时呈现。
使用redux提供的钩子连接reactredux

import { useSelector } from 'react-redux';
...
const store = useSelector(state => state);

字符串

相关问题