javascript - 使用 React Native 和 Mobx 创建主题全局类?

标签 javascript reactjs react-native jsx mobx

抱歉新手问题,但我仍然对将 React Native 与 Mobx 结合使用感到困惑。我想为可变主题创建全局商店。

import { observable, action, computed } from "mobx";

class ThemeStore {
    @observable primaryColor = "#FFCC33" ;
    @observable secondaryColor = "#4E3D2D";
    @observable whiteColor = "#FFF";

    constructor() {

    }

  }

  export const themeStore = new ThemeStore();

对于组件,themeStore 可以与 props 一起使用,也可以注入(inject)。但问题是如何将它与非组件一起使用,例如 StyleSheet 的示例,这样我就可以在样式 const 中使用 primaryColor。

我试过了:

@inject("themeStore")
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: themeStore.primaryColor
  },
  logo: {
    width: 20,
    height: 20
  }
});

但出现错误前导装饰器必须附加到类声明。所以我想问一下创建用于非组件的可变全局存储(变量)的正确方法是什么? 谢谢。

更新的代码示例:

@inject("foodDataStore", "navStore", "themeStore", "placeDataStore")
@observer
export class PlaceForm extends React.Component {
  constructor(props) {
    super(props);
    let foodDataStore = this.props.foodDataStore;
    let navStore = this.props.navStore;
    let themeStore = this.props.themeStore;
    let placeDataStore = this.props.placeDataStore;
    this.state = {
      foodDataStore,
      navStore,
      placeDataStore,
      themeStore,
      placeName: "",
      placeImage: "",
      address: "",
      category: "",
      foods: [],
      location: "",
      operationHours: "",
      telephone: "",
      email: "",
      tags: [],
      validationPlaceNameMessage: "",
      validationPlaceImageMessage: "",
      validationAddressMessage: "",
      validationCategoryMessage: "",
      validationLocationMessage: "",
      validationOperationHoursMessage: "",
      validationTelephoneMessage: "",
      validationEmailMessage: ""
    };
  }

  static navigationOptions = ({ navigation }) => ({
    title: "New Place",
    headerLeft: <BackButton navigation={navigation} />,
    headerRight: null,
    headerTintColor: COLOR_SECONDARY_LIGHT,
    headerStyle: {
      backgroundColor: COLOR_PRIMARY_LIGHT,
      marginTop: 20
    }
  });
  render() {
    const { navigation } = this.props.navigation;
    const { styleSheet } = this;
    let Tags = this.state.tags.map((item, index) => {
      return (
        <FormInput
          key={index}
          value={"#" + item}
          editable={false}
          selectTextOnFocus={false}
        />
      );
    });
    return (
      <View style={styleSheet.container}>
        <ScrollView>
          <Text h4 style={styleSheet.title}>
            Register New Place
          </Text>
          <FormLabel>Place Name</FormLabel>
          <FormInput
            onChangeText={name => this.validatePlaceName(name)}
            placeholder="Place Name..."
          />
          <FormValidationMessage>
            {" "}
            {this.state.validationPlaceNameMessage}{" "}
          </FormValidationMessage>

          <FormLabel>Category</FormLabel>
          <FormInput
            onChangeText={category => this.validateCategory(category)}
            placeholder="Category..."
          />
          <FormValidationMessage>
            {this.state.validationCategoryMessage}
          </FormValidationMessage>

          <FormLabel>Image</FormLabel>
          <FormInput
            onChangeText={imageSource => this.validatePlaceImage(imageSource)}
            placeholder="Image..."
          />
          <FormValidationMessage>
            {this.state.validationPlaceImageMessage}
          </FormValidationMessage>

          <FormLabel>Address</FormLabel>
          <FormInput
            onChangeText={address => this.validateAddress(address)}
            placeholder="Address..."
          />
          <FormValidationMessage>
            {this.state.validationAddressMessage}
          </FormValidationMessage>

          <View style={{ flex: 1, flexDirection: "row" }}>
            <FormLabel>Tags</FormLabel>
            <Icon
              name={"md-add-circle"}
              size={24}
              type="ionicon"
              color={this.state.themeStore.primaryLightColor}
              onPress={() => {
                this.addTag();
              }}
              style={styleSheet.iconAdd}
            />
          </View>
          <FormInput
            placeholder="Tags..."
            onChangeText={tag => {
              this.setState({ tag });
            }}
            value={this.state.tag}
            selectTextOnFocus={false}
          />
          {Tags}
          <FormValidationMessage />

          <Button
            style={styleSheet.button}
            title="Register Place"
            borderRadius={20}
            backgroundColor={this.state.themeStore.primaryLightColor}
            onPress={this.submitNewFood}
          />
          <View style={{ height: 25, backgroundColor: "white" }} />
        </ScrollView>
      </View>
    );
  }

  @computed
  get styleSheet() {
    const { themeStore } = this.props;
    const styles = StyleSheet.create({
      contentContainer: {
        paddingVertical: 20
      },
      container: {
        flex: 1,
        marginTop: 0,
        backgroundColor: "white"
      },
      logoContainer: {
        alignItems: "center",
        justifyContent: "center",
        marginBottom: 20
      },
      logo: {
        width: 50,
        height: 50
      },
      title: {
        textAlign: "center",
        marginBottom: 20
      },
      button: {
        marginTop: 20,
        ...Platform.select({
          ios: {
            width: 350
          },
          android: {
            width: 100
          }
        }),
        height: 48,
        marginBottom: 20,
        alignSelf: "center"
      },
      rating: {
        marginLeft: 15,
        backgroundColor: "transparent"
      },
      iconAdd: {
        marginTop: 10
      },
      iconClose: {
        ...Platform.select({
          ios: {
            marginTop: 20
          },
          android: {
            alignSelf: "flex-end"
          }
        })
      }
    });

    return styles;
  }
}

最佳答案

您可以使用 computed在你的 React 组件中,这样 StyleSheet 将在 observable 更改时更新:

// themeStore.js
class ThemeStore {
  @observable primaryColor = "#FFCC33" ;
  @observable secondaryColor = "#4E3D2D";
  @observable whiteColor = "#FFF";
}

export const themeStore = new ThemeStore();

// yourComponent.js
@inject("themeStore") @observer
class YourComponent extends React.Component {
  @computed get styleSheet() {
    const { themeStore } = this.props;
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
        backgroundColor: themeStore.primaryColor
      },
      logo: {
        width: 20,
        height: 20
      }
    });

    return styles;
  }

  render() {
    const { styleSheet } = this;

    return (
      <div className={styleSheet.container}> 
        <span className={styleSheet.logo}> Logo </span> 
      </div>
    );
  }
}

关于javascript - 使用 React Native 和 Mobx 创建主题全局类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46986511/

相关文章:

javascript - react 导航未定义错误

android - 哪个依赖性导致 “Failed resolution Failed resolution of: Lcom/google/android/gms/common/internal/zzab;”

javascript - jquery 加载带有 switch case 的页面

javascript - 如何使用 ReactCSStransitionGroup 或 ReactTransitionGroup 在 React JS 中向下滑动无状态组件?

javascript - 使用原型(prototype)获取单击事件上的 next() 元素的innerHTML

javascript - 避免打开文件选择弹出窗口

node.js - Sequelize.op 未定义

react-native - React Native 上的字母间距 - Android

JavaScript - 未捕获的语法错误 : Unexpected token ) when calling a function

javascript - 将用 jQuery 编码的图像 slider 转换为纯 JS