Context 上下文

Context解决了什么问题

在一个典型的React应用中,数据是通过props属性逐层传递,这种做法对于某些数据而言是极其繁琐的(如:登录信息、UI主题),这些数据应用中许多组件都需要;而Context提供了一种在组件间共享值的方式,而不必显式地通过组件树逐层传递。

实例演示:应用主题配置

  1. 分析实现效果,思考传统实现思路及问题
  2. 对比Context实现方式,体会Context的简洁和解耦
  3. 使用state维护动态Context值

使用Context的思考

  1. 因为Context本质上就是全局变量,大量使用Context会导致组件失去独立性,使组件复用性变差。
  2. 对于常规的组件间传值,可优先考虑组件组合、状态管理、单例导出等方式,不要过度使用Context。

ThemeContext.tsx

import { createContext } from 'react';

export const ThemeContext = createContext<string>('dark');

RootView.js


import React, { useState } from 'react';
import {
  View,
  Button
} from 'react-native';

import { ThemeContext } from './ThemeContext';

import PageView from './PageView';

export default () => {

    const [theme, setTheme] = useState('dark');

    return (
        <ThemeContext.Provider value={theme}>
            <Button title='切换主题' onPress={() => {
                setTheme(state => {
                    if (state === 'dark') {
                        return 'light';
                    } else {
                        return 'dark';
                    }
                })
            }} />
            <View style={{ width: '100%' }}>
                <PageView />
            </View>
        </ThemeContext.Provider>
    );
}

PageView.js

import React from 'react';
import {
  View,
} from 'react-native';

import Header from './Header';

export default () => {

    return (
        <View>
            <Header />
        </View>
    );
}

Header.js


import React, { useContext } from 'react';
import {
  StyleSheet,
  View,
  Image,
  Text,
} from 'react-native';

import icon_avatar from '../assets/images/default_avatar.png';

import { ThemeContext } from './ThemeContext';

export default () => {

    const theme = useContext(ThemeContext);

    const styles = theme === 'dark' ? darkStyles : lightStyles;
    return (
        <View style={styles.content}>
            <Image style={styles.img} source={icon_avatar} />
            <Text style={styles.txt}>个人信息介绍</Text>
            <View style={styles.infoLayout}>
                <Text style={styles.infoTxt}>
                    各位产品经理大家好,我是个人开发者张三,我学习RN两年半了,我喜欢安卓、RN、Flutter。
                </Text>
            </View>
        </View>
    );
}

const darkStyles = StyleSheet.create({
    content: {
        width: '100%',
        height: '100%',
        backgroundColor: '#353535',
        flexDirection: 'column',
        alignItems: 'center',
        paddingHorizontal: 16,
        paddingTop: 64,
    },
    img: {
        width: 96,
        height: 96,
        borderRadius: 48,
        borderWidth: 4,
        borderColor: '#ffffffE0',
    },
    txt: {
        fontSize: 24,
        color: 'white',
        fontWeight: 'bold',
        marginTop: 32,
    },
    infoLayout: {
        width: '90%',
        padding: 16,
        backgroundColor: '#808080',
        borderRadius: 12,
        marginTop: 24,
    },
    infoTxt: {
        fontSize: 16,
        color: 'white',
    },
});

const lightStyles = StyleSheet.create({
    content: {
        width: '100%',
        height: '100%',
        backgroundColor: '#fafafa',
        flexDirection: 'column',
        alignItems: 'center',
        paddingHorizontal: 16,
        paddingTop: 64,
    },
    img: {
        width: 96,
        height: 96,
        borderRadius: 48,
        borderWidth: 4,
        borderColor: '#00000080',
    },
    txt: {
        fontSize: 24,
        color: '#333333',
        fontWeight: 'bold',
        marginTop: 32,
    },
    infoLayout: {
        width: '90%',
        padding: 16,
        backgroundColor: '#EAEAEA',
        borderRadius: 12,
        marginTop: 24,
    },
    infoTxt: {
        fontSize: 16,
        color: '#666666',
    },
});
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容