https://github.com/facebook/react/blob/master/packages/react/src/ReactContext.js
export function createContext<T>(
defaultValue: T,
calculateChangedBits: ?(a: T, b: T) => number, // 一个方法,用来计算新老context变化(通过 Object.is() 计算新老context的差异)。
): ReactContext<T> {
if (calculateChangedBits === undefined) {
calculateChangedBits = null;
} else { }
const context: ReactContext<T> = {
$$typeof: REACT_CONTEXT_TYPE, // 与ReactElement的$$typeof不一样 是作为createElement中的属性type中的对象进行存储的。
_calculateChangedBits: calculateChangedBits,
/*
作为支持多个并发渲染器的解决方法,我们将一些渲染器分类为主要渲染器,将其他渲染器分类为辅助渲染器。
我们只希望最多有两个并发渲染器:React Native(主要)和Fabric(次要);
React DOM(主要)和React ART(次要)。
辅助渲染器将自己的context的value存储在单独的字段中。
<Provider value={xxx}>中的value就是赋值给_currentValue的,
也就是说_currentValue和_currentValue2作用是一样的,只是分别给主渲染器和辅助渲染器使用
_currentValue和_currentValue2作用一样,只是作用平台不同
*/
// 用来记录Prvoider上面提供的value有变化的情况下,就会更新到这个_currentValue上面,就是用来记录最新的context的值的
_currentValue: defaultValue,
_currentValue2: defaultValue,
_threadCount: 0, // 用来追踪该context的并发渲染器的数量
Provider: (null: any),
Consumer: (null: any),
};
context.Provider = {
$$typeof: REACT_PROVIDER_TYPE,
_context: context,
};
let hasWarnedAboutUsingNestedContextConsumers = false;
let hasWarnedAboutUsingConsumerProvider = false;
let hasWarnedAboutDisplayNameOnConsumer = false;
if (__DEV__) {
const Consumer = {
$$typeof: REACT_CONTEXT_TYPE,
_context: context,
_calculateChangedBits: context._calculateChangedBits,
};
// $FlowFixMe: Flow complains about not setting a value, which is intentional here
Object.defineProperties(Consumer, {
Provider: {
get() {
if (!hasWarnedAboutUsingConsumerProvider) {
hasWarnedAboutUsingConsumerProvider = true;
console.error(
'Rendering <Context.Consumer.Provider> is not supported and will be removed in ' +
'a future major release. Did you mean to render <Context.Provider> instead?',
);
}
return context.Provider;
},
set(_Provider) {
context.Provider = _Provider;
},
},
_currentValue: {
get() {
return context._currentValue;
},
set(_currentValue) {
context._currentValue = _currentValue;
},
},
_currentValue2: {
get() {
return context._currentValue2;
},
set(_currentValue2) {
context._currentValue2 = _currentValue2;
},
},
_threadCount: {
get() {
return context._threadCount;
},
set(_threadCount) {
context._threadCount = _threadCount;
},
},
Consumer: {
get() {
if (!hasWarnedAboutUsingNestedContextConsumers) {
hasWarnedAboutUsingNestedContextConsumers = true;
console.error(
'Rendering <Context.Consumer.Consumer> is not supported and will be removed in ' +
'a future major release. Did you mean to render <Context.Consumer> instead?',
);
}
return context.Consumer;
},
},
displayName: {
get() {
return context.displayName;
},
set(displayName) {
if (!hasWarnedAboutDisplayNameOnConsumer) {
console.warn(
'Setting `displayName` on Context.Consumer has no effect. ' +
"You should set it directly on the context with Context.displayName = '%s'.",
displayName,
);
hasWarnedAboutDisplayNameOnConsumer = true;
}
},
},
});
// $FlowFixMe: Flow complains about missing properties because it doesn't understand defineProperty
context.Consumer = Consumer;
} else {
context.Consumer = context;
}
if (__DEV__) {
context._currentRenderer = null;
context._currentRenderer2 = null;
}
return context;
}
新旧对比源码
export function calculateChangedBits<T>(
context: ReactContext<T>, // context
newValue: T,
oldValue: T,
) {
if (is(oldValue, newValue)) { // Object.is()
// No change
return 0;
} else {
const changedBits =
typeof context._calculateChangedBits === 'function'
? context._calculateChangedBits(oldValue, newValue)
: MAX_SIGNED_31_BIT_INT;
if (__DEV__) {
if ((changedBits & MAX_SIGNED_31_BIT_INT) !== changedBits) {
console.error(
'calculateChangedBits: Expected the return value to be a ' +
'31-bit integer. Instead received: %s',
changedBits,
);
}
}
// 返回 被改变的值(改变了);没有给改变返回 0
return changedBits | 0;
}
}