/** * Sets a subset of the state. Always use this to mutate * state. You should treat `this.state` as immutable. * 设置一个状态的子集, 永远要使用他来改变 state, 并且你应该视为 `this.state` 是不变的 * * There is no guarantee that `this.state` will be immediately updated, so * accessing `this.state` after calling this method may return the old value. * * 在这里不保证 `this.state` 会立即更新, 所以在调用此方法之后访问 `this.state` 会获得一个旧值 * * There is no guarantee that calls to `setState` will run synchronously, * as they may eventually be batched together. You can provide an optional * callback that will be executed when the call to setState is actually * completed. * * 在这里不保证 `setState` 是同步运行的, 他们可能是一起被批量处理的. 你可以提供一个回调函数,在 `setState` 执行完毕后会被运行. * * When a function is provided to setState, it will be called at some point in * the future (not synchronously). It will be called with the up to date * component arguments (state, props, context). These values can be different * from this.* because your function may be called after receiveProps but before * shouldComponentUpdate, and this new state, props, and context will not yet be * assigned to this. * * 如果给 setState 提供了一个函数, 它将会在未来被运行(不是同步), 它调用的时候会得到最新的(state, props, context) * 但是组件的其他 this.*(指 state, props, context) 可能不尽相同, 因为函数会在 receiveProps 之后 * 但是在 shouldComponentUpdate 之前运行,这个时候,新的 state 还没有合并到 this * * * @param {object|function} partialState Next partial state or function to * produce next partial state to be merged with current state. * 下一个局部的 state 或者通过函数生成 新的 state, 值将会被合并到当前的 state内 * @param {?function} callback Called after state is updated. 回调函数 * @final * @protected */ Component.prototype.setState = function (partialState, callback) { // 参数检查 invariant( typeof partialState === "object" || typeof partialState === "function" || partialState == null, "setState(...): takes an object of state variables to update or a " + "function which returns an object of state variables." ); // this.updater 是实际渲染器传入的,并非 React 核心提供. this.updater.enqueueSetState(this, partialState, callback, "setState"); };
/* * @param {?function} callback Called after update is complete. * @final * @protected */ // forceUpdate 和 setState 其中一个比较大的差异是 forceUpdate 不会触发 `shouldComponentUpdate` Component.prototype.forceUpdate = function (callback) { this.updater.enqueueForceUpdate(this, callback, "forceUpdate"); // 这里第三个参数不同 };
exportfunctioncreateElement(type, config, children) { // 省略一些信息,主要是 type 判断, config 检查 和 children 数量检查
returnReactElement( type, key, ref, self, source, ReactCurrentOwner.current, props ); } constReactElement = function (type, key, ref, self, source, owner, props) { const element = { // This tag allows us to uniquely identify this as a React Element // 这个标签永远使用一个独特的标识,来表名这是一个React Element // react 所有标识详见 packages/shared/ReactSymbols.js $$typeof: REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element type: type, key: key, ref: ref, props: props,
// Record the component responsible for creating this element. _owner: owner, };
// 如果 children 是 字符串 数字 或者单个 element对象则 invokeCallback = true if (invokeCallback) { const child = children; let mappedChild = callback(child); // 调用回调取到返回值 const childKey = nameSoFar === '' ? SEPARATOR + getElementKey(child, 0) : nameSoFar; // 生成一个 key if (Array.isArray(mappedChild)) { // 判断返回的是不是一个数组,如果是一个数组那么进行递归 let escapedChildKey = ''; if (childKey != null) { escapedChildKey = escapeUserProvidedKey(childKey) + '/'; } mapIntoArray(mappedChild, array, escapedChildKey, '', c => c); } elseif (mappedChild != null) { if (isValidElement(mappedChild)) { mappedChild = cloneAndReplaceKey( // cloneAndReplaceKey 是 ReactElement 的一个包装函数,具体制定了 element 对象的key mappedChild, // Keep both the (mapped) and old keys if they differ, just as // traverseAllChildren used to do for objects as children escapedPrefix + // $FlowFixMe Flow incorrectly thinks React.Portal doesn't have a key (mappedChild.key && (!child || child.key !== mappedChild.key) ? // $FlowFixMe Flow incorrectly thinks existing element's key can be a number escapeUserProvidedKey('' + mappedChild.key) + '/' : '') + childKey, ); } array.push(mappedChild); } return1; }
// 如果 children 不是单个元素或者原始类型 let child; let nextName; let subtreeCount = 0; // Count of children found in the current subtree. const nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;
functioncountChildren(children: ?ReactNodeList): number { let n = 0; mapChildren(children, () => { n++; // Don't return anything }); return n; }
React.Children.only
验证 children 是否只有一个子节点(一个 React 元素),如果有则返回它,否则此方法会抛出错误
1 2 3 4 5 6 7
function onlyChild<T>(children: T): T { invariant( isValidElement(children), "React.Children.only expected to receive a single React element child." ); return children; }
// an immutable object with a single mutable value // 一个具有可变值的不可变对象 exportfunctioncreateRef(): RefObject { const refObject = { current: null, }; if (__DEV__) { Object.seal(refObject); } return refObject; }
functionresolveDispatcher() { const dispatcher = ReactCurrentDispatcher.current; invariant( dispatcher !== null, "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for" + " one of the following reasons:\n" + "1. You might have mismatching versions of React and the renderer (such as React DOM)\n" + "2. You might be breaking the Rules of Hooks\n" + "3. You might have more than one copy of React in the same app\n" + "See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." ); return dispatcher; }