使用反应本机元素更改主题不起作用?

2024-03-09

我一直在使用 React Native 元素。我想为我的应用程序实现黑暗模式,但由于某种原因我无法获取主题道具<ThemeProvider/>当我的环境中的状态发生变化时发生变化。

这是我的上下文,其中有 darkTheme 和 lightTheme 对象。我也有一个lightThemeState使用 useState 这样我就可以从子组件设置该状态。

import React, { createContext, useState, useEffect } from "react";
import { AsyncStorage } from "react-native";

import { ThemeProvider } from "react-native-elements";
import lightTheme from "../themes/light";
import darkTheme from "../themes/dark";

export const ThemeModeContext = createContext();

export const ThemeContextProvider = (props) => {
  const [lightThemeState, setLightThemeState] = useState(true);

  const saveThemeState = async () => {
    if (lightThemeState) {
      await AsyncStorage.removeItem("lightThemeState");
    } else {
      await AsyncStorage.setItem(
        "lightThemeState",
        JSON.stringify(lightThemeState)
      );
    }
  };

  const getThemeState = async () => {
    currentMode = await AsyncStorage.getItem("lightThemeState");

    if (currentMode) {
      setLightThemeState(JSON.parse(currentMode));
    }
  };

  useEffect(() => {
    saveThemeState();
  }, [lightThemeState]);

  useEffect(() => {
    getThemeState();
  }, []);

  const currentTheme = lightThemeState ? lightTheme : darkTheme;

  console.log("LIGHT THEME STATE", lightThemeState); 
// When I log this after I used the setLigthThemeState in a child component. It gives the correct state ie true or false.
  console.log("COLOR OF THE THEMES BACKGROUND", currentTheme.colors.background);
// This also gives the correct background for the theme that is the "currentTheme" depending on the state. So this far, everything is correct.

  return (
    <ThemeModeContext.Provider value={[lightThemeState, setLightThemeState]}>
      <ThemeProvider theme={currentTheme}>{props.children}</ThemeProvider>
    </ThemeModeContext.Provider>
  );
};

export default ThemeContextProvider;

因为我有另一个用于其他逻辑的上下文。我结合<ThemeContextProvider/>与我的其他背景<JourneyContextProvider/>。就像这样:

import React from "react";
import ThemeContextProvider from "./themeStore";
import JourneyContextProvider from "./journeyStore";

export const CombinedStoreProvider = (props) => {
  return (
    <JourneyContextProvider>
      <ThemeContextProvider>{props.children}</ThemeContextProvider>
    </JourneyContextProvider>
  );
};

export default CombinedStoreProvider;

最后我将整个应用程序包装在我的<CombinedStoreProvider/>。就像这样。

import React from "react";
import { SafeAreaView } from "react-native";

import { createAppContainer, createSwitchNavigator } from "react-navigation";
import { createMaterialBottomTabNavigator } from "react-navigation-material-bottom-tabs";

import Icon from "react-native-vector-icons/Ionicons";

import MoreScreenfrom "./src/screens/MoreModal";
import CombinedStoreProvider from "./store/combinedStore";

const TabNavigator = createMaterialBottomTabNavigator(
  {
    MoreScreen: {
      screen: MoreScreen,
      navigationOptions: {
        title: "More",
        tabBarIcon: ({ tintColor }) => (
          <SafeAreaView>
            <Icon style={[{ color: tintColor }]} size={25} name={"ios-more"} />
          </SafeAreaView>
        ),
      },
    },
  },
  {
    theme: ({ darkTheme }) => console.log(darkTheme),
    barStyleDark: {
      backgroundColor: darkTheme.colors.background,
    },
    barStyleLight: {
      backgroundColor: lightTheme.colors.background,
    },
    shifting: false,
    labeled: true,
    initialRouteName: "MoreScreen",
    activeColor: "#E4DC93",
    inactiveColor: "#fff",
    barStyle: { backgroundColor: "transparent", height: 80, paddingTop: 10 },
  }
);

const AllRoutes = createSwitchNavigator(
  {
    PersonalSettings: {
      title: "Personal Settings",
      screen: PersonalSettings,
      header: ({ goBack }) => ({
        left: (
          <Icon
            name={"chevron-left"}
            onPress={() => {
              goBack();
            }}
          />
        ),
      }),
    },
    Tabs: {
      screen: TabNavigator,
    },
  },
  {
    initialRouteName: "Tabs",
  }
);

const AppContainer = createAppContainer(AllRoutes);

export default App = () => {
  return (
    <CombinedStoreProvider>
      <AppContainer />
    </CombinedStoreProvider>
  );
};

这是我的子组件,我在其中切换lightThemeState在我的背景下。但即使一切看起来都很棒ThemeContextProvider(我控制台记录状态和背景颜色,他们已成功更改主题)。但在这个组件中我只得到了前一个主题。即使当我切换该子组件时,该子组件会重新呈现,但就像什么都没有改变一样lightThemeState。我知道这一点是因为在我切换主题后,控制台再次登录该组件,但日志显示以前的主题颜色。这是子组件:

import React, { useContext, useState } from "react";
import { StyleSheet, View, Text } from "react-native";
import { LayoutView, ContainerView } from "../../components/styles";
import { ThemeModeContext } from "../../../store/themeStore";
import { Card, ListItem, Avatar, ThemeContext } from "react-native-elements";

import CustomButton from "../../components/CustomButton";

const INITIAL_PERSONAL_INFO_STATE = {
  name: "",
  username: "",
  profileImage: "",
  favoriteDestinations: [],
};

const MoreModal = (props) => {
  const [personalInfo, setPersonalInfo] = useState(INITIAL_PERSONAL_INFO_STATE);

  const [lightThemeState, setLightThemeState] = useContext(ThemeModeContext);
  const { theme } = useContext(ThemeContext);
  const { navigate } = props.navigation;

  const primaryColor = theme.colors.background;

  console.log("COLOR IN COMPONENT", primaryColor);
// The color is from the previous theme and even thou the state has changed in the state below
  console.log("LIGHT THEME STATE IN COMPONENT", lightThemeState);

  return (
    <LayoutView primaryColor={theme.colors.background}>
      <ContainerView>
        <View>
        </View>
        <Card
          title={"Settings"}
        >
          <ListItem
            title="Light mode"
            switch={{
              value: lightThemeState,
              onValueChange: (value) => setLightThemeState(value), 
// Here is where I set lighThemeState to false in my context

            }}
            bottomDivider
        </Card>
      </ContainerView>
      <CustomButton title={"Sign in"}></CustomButton>
    </LayoutView>
  );
};

export default MoreModal;

也许您问的 darkTheme 和 lightTheme 有问题?不,如果我将状态从 true 更改为 false 并重新加载应用程序。有用。 不知怎的,主题没有更新<ThemeProvider theme={currentTheme}/>。有人可以解释为什么吗?


您无法使用 React Native Elements 动态更改主题。不幸的是,这没有在任何地方记录 - 这是很重要的一点,因为大多数 RNE 用户会假设他们可以在运行时动态更改整个主题(嗯,我做到了)。

React Native Elements github 上有几个已解决的问题提到了这一点。 例如这个问题 https://github.com/react-native-elements/react-native-elements/issues/1714(2019 年 1 月)其中一位开发人员表示:

目前这是不可能的。 ThemeProvider 不允许在运行时更改其属性。这是因为对 ThemeProvider 的 props 的更改将触发树下所有组件的重新渲染。

UPDATE: You can动态改变主题,但你必须使用带主题 https://react-native-elements.github.io/react-native-elements/docs/customization.html#using-the-theme-in-your-own-componentsReact Native Elements 提供的 HOC(例如调用 withTheme 提供的 updateTheme 函数)。有一点额外的接线,但这是可行的。您可以将 HOC 包装在顶层附近,以便主题更新传播到所有子级。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用反应本机元素更改主题不起作用? 的相关文章

  • 应用程序位于前台时的 IOS Expo 推送通知

    从博览会文档中阅读 对于 iOS 明智的做法是处理以下推送通知 当应用程序处于前台时收到 因为否则用户 永远不会见到他们 应用程序运行时到达的通知 iOS 上的前台不会显示在系统通知列表中 A 常见的解决方案是手动显示通知 为了 例如 如果
  • 网站 YouTube 嵌入视频不断播放

    我正在使用 youtube 提供的 iframe 在我的网站上嵌入视频 我还使用了一个 css 弹出窗口 这是我从这个页面学到的http www pat burt com web development how to do a css po
  • VBA / HTML / jQuery 选择自动完成 - 在列表中选择

    我正在尝试使用 Excel 中的 VBA 在网站的列表中选择一个值 这不是一个 正常列表 该网站使用 jQuery 选择自动完成 如下所示 example http davidwalsh name demo jquery chosen ph
  • 如何使用 jest 模拟第三方库

    我正在开发一个node js应用程序使用nestjs我有一堂课叫LoggerService如下 export class LoggerService private logger Rollbar constructor this logge
  • 使用 CryptoJS 更改密钥 [重复]

    这个问题在这里已经有答案了 我正在使用 CryptoJS 来加密和解密文本 在这里 我只是获取消息并显示加密和解密消息 我使用DES算法进行加密和解密 这是我的 HTML 文件
  • Node.js - console.log 不显示数组中的项目,而是显示 [Object]

    我在注销对象内数组的内容时遇到问题 实际的物体看起来像这样 var stuff accepted item1 item2 rejected response Foo envelope from The sender to new item1
  • React-native-super-grid 在回调期间刷新网格

    我在网格中显示项目 并且每个项目都进行了分类 如果我按类别图像 我只想过滤所选类别的网格项目 这是我的实现代码 每当我按下一个类别时 我都会得到thispressRow 方法内的对象 但是this setState items catego
  • 在为 RXJS 可观察量编写测试时,如何避免让调度程序通过我的业务逻辑?

    我发现使某些测试通过的唯一方法是显式地将调度程序传递给函数 为了便于说明 请考虑以下函数 function doStuff stream return stream delay 100 filter x gt x 2 0 map x gt
  • 如果链接包含特定文本,jQuery 将类添加到 href

    我的网站上的列表中有一些动态填充的链接 这些链接链接到文件 是否可以使用 jQuery 查看文件名是否以 pdf 结尾 并在 href 或类似的链接文本以 mp3 结尾时添加一个类 例如 我的列表中有以下链接 文件1 pdf 歌曲1 mp3
  • Javascript - 将值从下拉框传递到 Google Maps API

    我正在使用 Google 地图 API 为一家出租车公司创建报价表 目前 用户在 2 个文本框中输入出发点和接载点 API 会计算两点之间的距离以及行程费用 我正在尝试添加两个具有设定位置的下拉框 以便用户可以选择这些位置之一或使用文本框输
  • Typeahead.js substringMatcher 函数说明

    我只是在做一些研究Typeahead js这是一个非常酷的图书馆 感谢文档 我已经成功地获得了一个基本的示例 该文档也非常好 但是我试图弄清楚以下代码块实际上在做什么 var substringMatcher function strs r
  • 淡出和循环一组 div 的最佳方式

    假设我有以下 div div class a You are funny div div class b You are smart div div class c You are cool div 最好的展示方式是什么div a持续 5
  • 将 javascript 整数转换为字节数组并返回

    function intFromBytes x var val 0 for var i 0 i lt x length i val x i if i lt x length 1 val val lt lt 8 return val func
  • 查询为空 Node Js Sequelize

    我正在尝试更新 Node js 应用程序中的数据 我和邮递员测试过 我的开发步骤是 从数据库 MySQL 获取ID为10的数据进行更新 gt gt 未处理的拒绝SequelizeDatabaseError 查询为空 我认识到 我使用了错误的
  • 当用户单击链接时,如何记录 MixPanel 事件?

    当用户单击某种类型的链接时 我试图在 MixPanel 中记录一个事件 我正在使用 JQuery 不引人注意地完成此操作 据我所知 我需要添加一个回调函数 以便在记录事件后将用户带到 URL 这是我正在使用的代码 不幸的是
  • JavaScript 代码在不使用 ActiveX 的情况下截取网站屏幕截图

    我有一个用户与之交互的 JavaScript 应用程序 我需要保存当前界面的外观 裁剪出我需要的部分 或者通过指定div只拍摄我需要的部分 然后发送回服务器 显然任何外部服务都无法做到这一点 我需要一个 JavaScript 或Flash
  • JavaScript onresize 事件多次触发

    我在尝试仅在触发 onresize 事件时运行一次函数时遇到一些麻烦 我已经看过这个问题DOM onresize 事件 https stackoverflow com questions 1500312 javascript onresiz
  • 单击引导分页链接时调用 jquery 函数

    我想在单击引导分页链接时调用 jquery 函数 假设我想从第1页遍历到第2页 应该调用一个jquery函数 我正在使用以下代码 但它不起作用 ul pagination on click li function alert page ch
  • 需要有关 React Js 的帮助

    我是 React Js 新手 我的代码无法正常工作 请看下面 这是我的脚本文件Main jsx 该文件由 React 编译 输出放置在 dist 文件夹下的 main js 文件中 var react require react react
  • 在 Javascript 中减少/分组数组

    基于this https stackoverflow com a 40774906 3254598例如 我想以稍微不同的方式按对象进行分组 结果应该如下 key audi items make audi model r8 year 2012

随机推荐