【问题标题】:React hooks, state is not changing correctly反应钩子,状态没有正确改变
【发布时间】:2020-04-26 01:21:27
【问题描述】:

在这个项目中我使用了react hooks,这个sn-p用来改变项目的颜色主题,但是有一个我无法解决的问题。 常量 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 sit 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.)


【问题讨论】:

  • 你能添加你的 ActionReducer 以及你在哪里 console.log 状态吗?
  • 您需要发布您的 ActionReducer 和主题 reducer 代码,以便我们帮助您找到任何问题
  • @Domino987,我固定了减速器
  • 你在哪里记录它;)
  • @Domino987 在 if 运算符之前,看看

标签: javascript reactjs react-hooks


【解决方案1】:

最初的主题是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)

【讨论】:

  • 谢谢,伙计,你太棒了,我现在没有反应在渲染后创建新的引用,所以我只是把这个对象从函数中解决了,再次感谢你)))跨度>
  • @AlexKhanas 作为替代方案,请检查我的答案,它值得一票:)
【解决方案2】:

您需要在按钮单击时切换主题:

所以你可以这样做:

主题状态

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>
  );
};

ActionReducer:

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";

Codesandbox

【讨论】:

    【解决方案3】:

    我创建了一个关于这种行为could be implemented 的最小示例:

    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>
      );
    }
    
    

    由于您没有提供所有相关代码(例如reducer),我无法解释您的代码。

    【讨论】:

    • 我现在提供reducer
    猜你喜欢
    • 1970-01-01
    • 2020-03-09
    • 2020-05-18
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 2021-01-31
    • 2021-08-25
    • 1970-01-01
    相关资源
    最近更新 更多