Skip to content

React Native 使用

relationship-ts 特别优化了 React Native 环境的兼容性。

为什么需要 TypeScript 版本?

在 React Native 移动端使用原版 JS 包时,可能会遇到以下错误:

ERROR [RangeError: Property storage exceeds 196607 properties]

这是由于 JavaScriptCore 引擎对对象属性数量的限制(约 196607 个),而原版 JS 包在初始化时会创建大量对象属性。

TypeScript 版本通过以下优化解决了这个问题:

  • ✅ 使用 Map 代替 Object 存储数据
  • ✅ 实现 LRU 缓存机制,按需加载
  • ✅ 优化数据结构,减少内存占用

安装

bash
npm install relationship-ts

基础使用

函数式组件

tsx
import React, { useState } from 'react';
import { View, Text, TextInput, Button, StyleSheet } from 'react-native';
import relationship from 'relationship-ts';

export default function RelationshipApp() {
  const [input, setInput] = useState('');
  const [result, setResult] = useState<string[]>([]);

  const handleCalculate = () => {
    const output = relationship({ text: input });
    setResult(output);
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>中国亲戚关系计算器</Text>

      <TextInput
        style={styles.input}
        value={input}
        onChangeText={setInput}
        placeholder="输入关系,如:爸爸的妈妈"
      />

      <Button title="计算" onPress={handleCalculate} />

      <View style={styles.resultContainer}>
        {result.map((item, index) => (
          <Text key={index} style={styles.result}>{item}</Text>
        ))}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
    textAlign: 'center',
  },
  input: {
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 8,
    padding: 12,
    fontSize: 16,
    marginBottom: 16,
  },
  resultContainer: {
    marginTop: 20,
  },
  result: {
    fontSize: 18,
    marginBottom: 8,
  },
});

带性别选择的组件

tsx
import React, { useState } from 'react';
import { View, Text, TextInput, Button, StyleSheet, Picker } from 'react-native';
import relationship from 'relationship-ts';

export default function RelationshipApp() {
  const [input, setInput] = useState('');
  const [sex, setSex] = useState<-1 | 0 | 1>(-1);
  const [reverse, setReverse] = useState(false);
  const [result, setResult] = useState<string[]>([]);

  const handleCalculate = () => {
    const output = relationship({ text: input, sex, reverse });
    setResult(output);
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>中国亲戚关系计算器</Text>

      <TextInput
        style={styles.input}
        value={input}
        onChangeText={setInput}
        placeholder="输入关系,如:爸爸的妈妈"
      />

      <Text style={styles.label}>您的性别:</Text>
      <Picker
        selectedValue={sex}
        onValueChange={(value) => setSex(value as -1 | 0 | 1)}
      >
        <Picker.Item label="未知" value={-1} />
        <Picker.Item label="女性" value={0} />
        <Picker.Item label="男性" value={1} />
      </Picker>

      <Button
        title={`反向查询: ${reverse ? '开' : '关'}`}
        onPress={() => setReverse(!reverse)}
      />

      <View style={styles.buttonContainer}>
        <Button title="计算" onPress={handleCalculate} />
      </View>

      <View style={styles.resultContainer}>
        {result.map((item, index) => (
          <Text key={index} style={styles.result}>{item}</Text>
        ))}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
    textAlign: 'center',
  },
  input: {
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 8,
    padding: 12,
    fontSize: 16,
    marginBottom: 16,
  },
  label: {
    fontSize: 16,
    marginBottom: 8,
  },
  buttonContainer: {
    marginTop: 16,
    marginBottom: 16,
  },
  resultContainer: {
    marginTop: 20,
  },
  result: {
    fontSize: 18,
    marginBottom: 8,
  },
});

使用方言

tsx
import React, { useState } from 'react';
import { View, Text, TextInput, Button, StyleSheet, Picker } from 'react-native';
import relationship from 'relationship-ts';
import { guangdong } from 'relationship-ts/locale/guangdong';

// 设置方言模式
relationship.setMode('guangdong', guangdong.data);

export default function RelationshipApp() {
  const [input, setInput] = useState('');
  const [mode, setMode] = useState('default');
  const [result, setResult] = useState<string[]>([]);

  const handleCalculate = () => {
    const output = relationship({ text: input, mode });
    setResult(output);
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>中国亲戚关系计算器</Text>

      <TextInput
        style={styles.input}
        value={input}
        onChangeText={setInput}
        placeholder="输入关系,如:妈妈的妈妈"
      />

      <Text style={styles.label}>方言:</Text>
      <Picker
        selectedValue={mode}
        onValueChange={(value) => setMode(value)}
      >
        <Picker.Item label="普通话" value="default" />
        <Picker.Item label="粤语" value="guangdong" />
      </Picker>

      <View style={styles.buttonContainer}>
        <Button title="计算" onPress={handleCalculate} />
      </View>

      <View style={styles.resultContainer}>
        {result.map((item, index) => (
          <Text key={index} style={styles.result}>{item}</Text>
        ))}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
    textAlign: 'center',
  },
  input: {
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 8,
    padding: 12,
    fontSize: 16,
    marginBottom: 16,
  },
  label: {
    fontSize: 16,
    marginBottom: 8,
  },
  buttonContainer: {
    marginTop: 16,
    marginBottom: 16,
  },
  resultContainer: {
    marginTop: 20,
  },
  result: {
    fontSize: 18,
    marginBottom: 8,
  },
});

性能建议

  1. 避免频繁切换模式:模式切换会清除缓存,建议在应用初始化时设置方言
  2. 复用结果:相同查询会自动命中 LRU 缓存
  3. 合理使用性别参数:某些查询需要指定性别才能获得准确结果

下一步

基于 MIT 许可发布