簡體   English   中英

反應鈎子,狀態沒有正確改變

[英]React hooks, state is not changing correctly

在這個項目中,我使用了 React 鈎子,這個片段用於改變項目的顏色主題,但有一個我無法解決的問題。 const lightTheme = { ... }

  const darkTheme = {
     ...
  }
 export const ThemeState = ({children}) => {

  const initialState = {
     theme: lightTheme
  }

  const [state, dispatch] = useReducer(ActionReducer, initialState)

  const {theme} = state 

  const themeToggler = (e) => {
     e.preventDefault()
     console.log(theme)
     if(theme == lightTheme){
        dispatch({type:THEME, payload: darkTheme})
     }
     else if(theme == darkTheme){
        dispatch({type:THEME, payload: lightTheme})
     }
   }

Lorem ipsum dolor sat amet,consectetur adipiscing elit,sed do eiusmod tempor incididunt ut Labore et dolore magna aliqua。

我的減速機:

export const ActionReducer = (state, action) => {
         switch(action.type) {
           case THEME:
             return{
               ...state,
               theme: action.payload
            }
           default:
              return state
   }
};

Here is component with toggle button by each click, I need to change theme in state, it clicks correctly: 
import {ThemeContext} from '../../store/themeState'

function Main () {
  const {theme, themeToggler} = useContext(ThemeContext)
   return (
       <button onClick={e => {themeToggler(e)}}></button>
   )
}

 export default Main

 when I press the button i catch this log


    ({body: "#E2E2E2", text: "#363537"}
      {body: "#363537", text: "#FAFAFA"}
      {body: "#363537", text: "#FAFAFA"}
      ....)

I don't know why do state changes like this. If you can, help me to solve this bug.)


初始主題是body: '{#E2E2E2', text: '#363537'}

當您單擊按鈕時,您會記錄此主題{body: "#E2E2E2", text: "#363537"} ,這正是您的初始主題。

登錄后,將主題更新為深色主題{body: '#363537', text: '#FAFAFA'}

這將被記錄,一旦您再次單擊按鈕: {body: "#363537", text: "#FAFAFA"}

現在問題來了,由於您在每次渲染時都創建了 darkTheme 對象,因此引用與之前的不一樣,因此else if(theme == darkTheme)失敗,因為 darkTheme 對象與之前的 darkTheme 對象不同。

要么將主題對象生成移出組件,這樣您就不會在每次渲染時生成一個新對象或向主題添加類型:

const lightTheme = {
  body: '#E2E2E2',
  text: '#363537',
  type: "light"
}`

並比較那些: if(theme.type == darkTheme.type)

您需要的是在按鈕單擊時切換主題:

所以你可以這樣做:

主題狀態

import React, { useReducer } from "react";
import { TOGGLE_THEME } from "./ActionTypes";
import ActionReducer from "./ActionReducer";

const lightTheme = {
  body: "#E2E2E2",
  text: "#363537"
};

const darkTheme = {
  body: "#363537",
  text: "#FAFAFA"
};

const initialState = {
  isLightTheme: true
};

export const ThemeState = ({ children }) => {
  const [state, dispatch] = useReducer(ActionReducer, initialState);

  const { isLightTheme } = state;

  const themeToggler = e => {
    e.preventDefault();
    dispatch({ type: TOGGLE_THEME });
  };

  const backgroundColor = isLightTheme ? lightTheme.body : darkTheme.body;
  const fontColor = isLightTheme ? lightTheme.text : darkTheme.text;

  return (
    <div style={{ backgroundColor: `${backgroundColor}` }}>
      <p style={{ color: `${fontColor}` }}>Some Text</p>
      <button type="submit" onClick={themeToggler}>
        Toggle Theme
      </button>
      <hr />
      Current Theme: {isLightTheme ? "light" : "dark"}
    </div>
  );
};

動作減速器:

import { TOGGLE_THEME } from "./ActionTypes";

export default function(state, action) {
  switch (action.type) {
    case TOGGLE_THEME:
      return {
        ...state,
        isLightTheme: !state.isLightTheme
      };
    default:
      return state;
  }
}

動作類型:

export const TOGGLE_THEME = "TOGGLE_THEME";

代碼沙盒

我創建了這種行為如何小例子可以實現

const darkTheme = {
  color: "green"
};

const lightTheme = {
  color: "red"
};

export default function App() {
  const [useLightTheme, setUseLightTheme] = useState(true);

  return (
    <div className={useLightTheme ? darkTheme.color : lightTheme.color}>
      <button onClick={() => setUseLightTheme(!useLightTheme)}>toggle</button>
      some example text
    </div>
  );
}

由於您沒有提供所有相關代碼(例如減速器),我無法解釋您的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM