[英]React with Hooks: how to correctly update state after a click event?
[英]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.