# 大纲

Context大纲 (opens new window) 密码:3279

# 老版本中的context

import propsTypes from 'proptypes';
import React, { Component } from 'react';

// 提供者
export default class ProviderDemo extends Component {
	getChildContext() {
		const info = {
			name: 'f',
			age: 18
		};
		return { info };
	}
	render() {
		return <ConsumerDemo />;
	}
}

ProviderDemo.childContextTypes = {
	info: propsTypes.object
};

// 消费者
class ConsumerDemo extends Component {
	render() {
		const { name, age } = this.context.info;
		return (
			<div>
				姓名:{name} 年龄:{age}
			</div>
		);
	}
}

ConsumerDemo.contextTypes = {
	info: propsTypes.object
};

# 新版本中的context

# 提供者

# 消费者

方式一:contextType

这种方式只能在类组件中使用。

import React, { createContext, Component } from 'react';

const UserInfoContext = createContext(null);
const UserInfoProvider = UserInfoContext.Provider;
export default class ProviderDemo extends Component {
	state = {
		name: 'f',
		age: 18
	};
	render() {
		return (
			<UserInfoProvider value={this.state}>
				<ConsumerDemo />
			</UserInfoProvider>
		);
	}
}

// 消费者
class ConsumerDemo extends Component {
	render() {
		const { name, age } = this.context;
		return (
			<div>
				name:{name} age:{age}
			</div>
		);
	}
}

ConsumerDemo.contextType = UserInfoContext;

方法二:useContext

这种方式,只能在函数组件中使用。

import React, { createContext, Component, useContext } from 'react';

const UserInfoContext = createContext(null);
const UserInfoProvider = UserInfoContext.Provider;
export default class ProviderDemo extends Component {
	state = {
		name: 'f',
		age: 18
	};
	render() {
		return (
			<UserInfoProvider value={this.state}>
				<ConsumerDemo />
			</UserInfoProvider>
		);
	}
}

// 消费者
function ConsumerDemo() {
	const { name, age } = useContext(UserInfoContext);
	return (
		<div>
			name:{name} age:{age}
		</div>
	);
}

方法三:Consumer

这种方式,函数组件和类组件中都可以使用。

import React, { createContext, Component } from 'react';

const UserInfoContext = createContext(null);
const UserInfoProvider = UserInfoContext.Provider;
export default class ProviderDemo extends Component {
	state = {
		name: 'f',
		age: 15
	};
	render() {
		return (
			<UserInfoProvider value={this.state}>
				<ConsumerDemo />
			</UserInfoProvider>
		);
	}
}

// 消费者 函数组件
// const UserInfoConsumer = UserInfoContext.Consumer;
// function ConsumerDemo() {
// 	return (
// 		<UserInfoConsumer>
// 			{({ name, age }) => (
// 				<div>
// 					name:{name} age:{age}
// 				</div>
// 			)}
// 		</UserInfoConsumer>
// 	);
// }

// 消费者 类组件
const UserInfoConsumer = UserInfoContext.Consumer;
class ConsumerDemo extends Component {
	render() {
		return (
			<UserInfoConsumer>
				{({ name, age }) => (
					<div>
						name:{name} age:{age}
					</div>
				)}
			</UserInfoConsumer>
		);
	}
}

# 动态context

import React, { createContext, useContext, useState, memo } from 'react';

const UserContext = createContext(null);
const UserProvider = UserContext.Provider;

export default () => {
	const [ contextValue, setContextValue ] = useState({ name: 'f', age: 17 });
	return (
		<div>
			<UserProvider value={contextValue}>
				<ConsumerDemo />
			</UserProvider>
			<button onClick={() => setContextValue({ ...contextValue, age: 18 })}>改变年龄</button>
		</div>
	);
};

const ConsumerDemo = memo(() => {
	const { name, age } = useContext(UserContext);
	return (
		<div>
			name: {name}, age: {age}
		</div>
	);
});

# context高阶用法

# 嵌套 Provider

import React, { createContext, memo, useState } from 'react';

const ThemeContext = createContext(null);
const LanguageContext = createContext(null);

const ThemeProvider = ThemeContext.Provider;
const LanguageProvider = LanguageContext.Provider;

const ThemeConsumer = ThemeContext.Consumer;
const LanguageConsumer = LanguageContext.Consumer;

const ConsumerDemo = memo(() => {
	return (
		<ThemeConsumer>
			{(theme) => (
				<LanguageConsumer>
					{(language) => {
						const { color, background } = theme;
						return <div style={{ color, background }}>{language}</div>;
					}}
				</LanguageConsumer>
			)}
		</ThemeConsumer>
	);
});

export default () => {
	const [ language, setLanguage ] = useState('ch');
	const [ theme, setTheme ] = useState({ color: 'red', background: 'orange' });

	return (
		<ThemeProvider value={theme}>
			<LanguageProvider value={language}>
				<ConsumerDemo />
			</LanguageProvider>
		</ThemeProvider>
	);
};

# 逐层传递 Provider

import React, { createContext, useContext } from 'react';

const LanguageContext = createContext(null);
const LanguageProvider = LanguageContext.Provider;

const ConsumerDemo2 = () => {
	const language = useContext(LanguageContext);
	return <span>{language}</span>;
};

const ConsumerDemo1 = () => {
	const language = useContext(LanguageContext);
	return (
		<div>
			{language}
			<LanguageProvider value="en">
				<ConsumerDemo2 />
			</LanguageProvider>
		</div>
	);
};

export default () => {
	return (
		<LanguageProvider value="ch">
			<ConsumerDemo1 />
		</LanguageProvider>
	);
};

# 问答

context 与 props 和 react-redux 的对比?

context:

  • 解决了 props 需要每一层都手动添加 props 的缺陷。
  • 解决了改变 value ,组件全部重新渲染的缺陷。

react-redux 就是通过 Provider 模式把 redux 中的 store 注入到组件中的。