mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Previous behavior: `transferPropsTo(<div style={{color: 'red'}} />)` would get `color` overriden if we transfer in a `style={{color: 'blue'}}`. This is inconsistent with how other props are transfered.
This simply reverses the order of arguments.
closes #1435
163 lines
4.6 KiB
JavaScript
163 lines
4.6 KiB
JavaScript
/**
|
|
* Copyright 2013-2014 Facebook, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* @providesModule ReactPropTransferer
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
var emptyFunction = require('emptyFunction');
|
|
var invariant = require('invariant');
|
|
var joinClasses = require('joinClasses');
|
|
var merge = require('merge');
|
|
|
|
/**
|
|
* Creates a transfer strategy that will merge prop values using the supplied
|
|
* `mergeStrategy`. If a prop was previously unset, this just sets it.
|
|
*
|
|
* @param {function} mergeStrategy
|
|
* @return {function}
|
|
*/
|
|
function createTransferStrategy(mergeStrategy) {
|
|
return function(props, key, value) {
|
|
if (!props.hasOwnProperty(key)) {
|
|
props[key] = value;
|
|
} else {
|
|
props[key] = mergeStrategy(props[key], value);
|
|
}
|
|
};
|
|
}
|
|
|
|
var transferStrategyMerge = createTransferStrategy(function(a, b) {
|
|
// `merge` overrides the first object's (`props[key]` above) keys using the
|
|
// second object's (`value`) keys. An object's style's existing `propA` would
|
|
// get overridden. Flip the order here.
|
|
return merge(b, a);
|
|
});
|
|
|
|
/**
|
|
* Transfer strategies dictate how props are transferred by `transferPropsTo`.
|
|
* NOTE: if you add any more exceptions to this list you should be sure to
|
|
* update `cloneWithProps()` accordingly.
|
|
*/
|
|
var TransferStrategies = {
|
|
/**
|
|
* Never transfer `children`.
|
|
*/
|
|
children: emptyFunction,
|
|
/**
|
|
* Transfer the `className` prop by merging them.
|
|
*/
|
|
className: createTransferStrategy(joinClasses),
|
|
/**
|
|
* Never transfer the `key` prop.
|
|
*/
|
|
key: emptyFunction,
|
|
/**
|
|
* Never transfer the `ref` prop.
|
|
*/
|
|
ref: emptyFunction,
|
|
/**
|
|
* Transfer the `style` prop (which is an object) by merging them.
|
|
*/
|
|
style: transferStrategyMerge
|
|
};
|
|
|
|
/**
|
|
* Mutates the first argument by transferring the properties from the second
|
|
* argument.
|
|
*
|
|
* @param {object} props
|
|
* @param {object} newProps
|
|
* @return {object}
|
|
*/
|
|
function transferInto(props, newProps) {
|
|
for (var thisKey in newProps) {
|
|
if (!newProps.hasOwnProperty(thisKey)) {
|
|
continue;
|
|
}
|
|
|
|
var transferStrategy = TransferStrategies[thisKey];
|
|
|
|
if (transferStrategy && TransferStrategies.hasOwnProperty(thisKey)) {
|
|
transferStrategy(props, thisKey, newProps[thisKey]);
|
|
} else if (!props.hasOwnProperty(thisKey)) {
|
|
props[thisKey] = newProps[thisKey];
|
|
}
|
|
}
|
|
return props;
|
|
}
|
|
|
|
/**
|
|
* ReactPropTransferer are capable of transferring props to another component
|
|
* using a `transferPropsTo` method.
|
|
*
|
|
* @class ReactPropTransferer
|
|
*/
|
|
var ReactPropTransferer = {
|
|
|
|
TransferStrategies: TransferStrategies,
|
|
|
|
/**
|
|
* Merge two props objects using TransferStrategies.
|
|
*
|
|
* @param {object} oldProps original props (they take precedence)
|
|
* @param {object} newProps new props to merge in
|
|
* @return {object} a new object containing both sets of props merged.
|
|
*/
|
|
mergeProps: function(oldProps, newProps) {
|
|
return transferInto(merge(oldProps), newProps);
|
|
},
|
|
|
|
/**
|
|
* @lends {ReactPropTransferer.prototype}
|
|
*/
|
|
Mixin: {
|
|
|
|
/**
|
|
* Transfer props from this component to a target component.
|
|
*
|
|
* Props that do not have an explicit transfer strategy will be transferred
|
|
* only if the target component does not already have the prop set.
|
|
*
|
|
* This is usually used to pass down props to a returned root component.
|
|
*
|
|
* @param {ReactDescriptor} descriptor Component receiving the properties.
|
|
* @return {ReactDescriptor} The supplied `component`.
|
|
* @final
|
|
* @protected
|
|
*/
|
|
transferPropsTo: function(descriptor) {
|
|
invariant(
|
|
descriptor._owner === this,
|
|
'%s: You can\'t call transferPropsTo() on a component that you ' +
|
|
'don\'t own, %s. This usually means you are calling ' +
|
|
'transferPropsTo() on a component passed in as props or children.',
|
|
this.constructor.displayName,
|
|
descriptor.type.displayName
|
|
);
|
|
|
|
// Because descriptors are immutable we have to merge into the existing
|
|
// props object rather than clone it.
|
|
transferInto(descriptor.props, this.props);
|
|
|
|
return descriptor;
|
|
}
|
|
|
|
}
|
|
};
|
|
|
|
module.exports = ReactPropTransferer;
|