简体   繁体   English

React App 仅在第一次状态更改时重新渲染,即使更改成功,第二次更改也看不到更改

[英]React App only re-renders on first state change and changes are not visible for second change even though the change is successful

I am tryin to implement dark mode in a React app.我正在尝试在 React 应用程序中实现暗模式。 I have given a toggle on my child component to change the theme to dark mode.我在我的子组件上进行了切换,以将主题更改为暗模式。 So lets say if we start with dark mode and we click on toggle then theme changes to light one.因此,假设我们从暗模式开始并单击切换,然后主题更改为亮模式。 Now, if toggle a second time, the theme does not change but the state value does change.现在,如果再次切换,主题不会改变,但状态值会改变。

As I understand, if a state changes component should re-render and it does so but only once!据我了解,如果一个状态发生变化,组件应该重新渲染,而且它只会重新渲染一次!

Please let me know what is going wrong.请让我知道出了什么问题。

App.js
------
import themes from '../theme';
import Container from '../common/container';

const App = function(props) {

 const [darkMode, setDarkMode] = React.useState(true);

 const changeTheme = function(){
  console.log('Dark Mode is ' + darkMode + ', Setting it to ' + !darkMode)
  setDarkMode(!darkMode)
 }
 
 return (
  <Router>
    <ThemeProvider theme={ darkMode ? themes.darkTheme : themes.lightTheme}>
      <CssBaseline />
      <Container darkMode={darkMode} changeTheme={changeTheme}>
        </Container>
    </ThemeProvider>
  </Router>
 );
}

As you can see the App component has state darkMode and its toggle is passed to the child component Container.如您所见,App 组件的状态为 darkMode,并且其切换被传递给子组件 Container。

Container.js
------------

const Container = function(props) {
 return (
  <Box>
    <AppBar position="static">
        <Toolbar>
            .
            .
          <IconButton color="primary" onClick={(event) => props.changeTheme()}>{ props.darkMode ?
          <Brightness4Icon /> : <BrightnessHighIcon /> }</IconButton>

           <Button variant="contained" color="primary">Login</Button>
        </Toolbar>
    </AppBar>
    <Box>
      {props.children}
    </Box>
  </Box>
 )
}

So in Container component, if you click on IconButton, the changeTheme funtion of App Component will be called.所以在Container组件中,如果点击IconButton,就会调用App组件的changeTheme函数。

Now, the result of this code is - I am able to change the theme only on first click be it dark mode first or light mode first.现在,这段代码的结果是 - 我只能在第一次点击时更改主题,无论是先暗模式还是先亮模式。 The Second and further clicks does not change the theme.第二次和进一步的点击不会改变主题。

Also, as you have noticed I have a log statement in changeTheme.另外,正如您所注意到的,我在 changeTheme 中有一个日志语句。 PF the attached console screenshot. PF 附加的控制台屏幕截图。 在此处输入图片说明

So, as per my understanding App should re-render if darkMode changes.因此,根据我的理解,如果 darkMode 更改,应用程序应该重新渲染。 But is only does for the first time.但只是第一次做。

Thanks for your help!谢谢你的帮助!

I am not exactly sure what is wrong with your code, but if you are using Context there is no need to pass darkMode to Container .我不确定您的代码有什么问题,但是如果您使用的是Context ,则无需将 darkMode 传递给Container

I made a quick working example off of your code, modify it to fit your needs.我根据您的代码制作了一个快速工作示例,对其进行修改以满足您的需要。

import React from 'react'
import ReactDOM from 'react-dom'

const ThemeContext = React.createContext("light");

function App() {
  const [darkMode, setDarkMode] = React.useState(true);

  const changeTheme = function(){
    console.log('Dark Mode is ' + darkMode + ', Setting it to ' + !darkMode)
    setDarkMode(!darkMode)
 }  

  return (
    <ThemeContext.Provider value={darkMode ? "dark" : "light"}>
      <Container changeTheme={changeTheme}/>
    </ThemeContext.Provider>
  )
}

function Container({changeTheme}) {
  const theme = React.useContext(ThemeContext);

  return <React.Fragment>
    {theme}

    <button onClick={changeTheme}>Toggle Theme</button>
  </React.Fragment>;
}

ReactDOM.render(
  <App />,
  document.getElementById('container')
);

As you can see, in the Container you can use useContext to get the theme value, there is no need to pass it as a property, that's the whole point of contexts.如您所见,在Container您可以使用useContext来获取主题值,无需将其作为属性传递,这就是上下文的全部意义所在。

You can test the code above in this CodeSandbox您可以在此CodeSandbox 中测试上面的代码

If this is unclear, you can read more about the useContext hook in the React Docs .如果不清楚,您可以在React Docs 中阅读有关useContext钩子的更多信息。 There is also an example of theme context implementation.还有一个主题上下文实现的例子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM