Skip to content

Commit

Permalink
Introduce a supported way to slice children
Browse files Browse the repository at this point in the history
Introduces a counterpart to mapChildren. It excludes empty children just as
mapChildren for compatibility. With might introduce something like
sliceChildrenIncludingEmptyValues at some point.
  • Loading branch information
sebmarkbage authored and zpao committed Jul 3, 2013
1 parent b6451be commit d501485
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 0 deletions.
119 changes: 119 additions & 0 deletions src/utils/__tests__/sliceChildren-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**
* Copyright 2013 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.
*
* @emails react-core
* @jsx React.DOM
*/

"use strict";

describe('sliceChildren', function() {

var React;
var ReactTestUtils;

var sliceChildren;
var reactComponentExpect;

var Partial;

beforeEach(function() {
React = require('React');
ReactTestUtils = require('ReactTestUtils');

sliceChildren = require('sliceChildren');
reactComponentExpect = require('reactComponentExpect');

Partial = React.createClass({
render: function() {
return (
<div>
{sliceChildren(
this.props.children,
this.props.start,
this.props.end
)}
</div>
);
}
});
});

function renderAndSlice(set, start, end) {
var instance = <Partial start={start} end={end}>{set}</Partial>;
ReactTestUtils.renderIntoDocument(instance);
var rendered = reactComponentExpect(instance)
.expectRenderedChild()
.instance();
return rendered.props.children;
}

it('should render the whole set if start zero is supplied', function() {
var fullSet = [
<div key="A" />,
<div key="B" />,
<div key="C" />
];
var children = renderAndSlice(fullSet, 0);
expect(children).toEqual({
'[A]': fullSet[0],
'[B]': fullSet[1],
'[C]': fullSet[2]
});
});

it('should render the remaining set if no end index is supplied', function() {
var fullSet = [
<div key="A" />,
<div key="B" />,
<div key="C" />
];
var children = renderAndSlice(fullSet, 1);
expect(children).toEqual({
'[B]': fullSet[1],
'[C]': fullSet[2]
});
});

it('should exclude everything at or after the end index', function() {
var fullSet = [
<div key="A" />,
<div key="B" />,
<div key="C" />,
<div key="D" />
];
var children = renderAndSlice(fullSet, 1, 2);
expect(children).toEqual({
'[B]': fullSet[1]
});
});

it('should allow static children to be sliced', function() {
var a = <div />;
var b = <div />;
var c = <div />;

var instance = <Partial start={1} end={2}>{a}{b}{c}</Partial>;
ReactTestUtils.renderIntoDocument(instance);
var rendered = reactComponentExpect(instance)
.expectRenderedChild()
.instance();

expect(rendered.props.children).toEqual({
'[1]': b
});
});

});
59 changes: 59 additions & 0 deletions src/utils/sliceChildren.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* Copyright 2013 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 sliceChildren
*/

"use strict";

var flattenChildren = require('flattenChildren');

/**
* Slice children that are typically specified as `props.children`. This version
* of slice children ignores empty child components.
*
* @param {*} children The children set to filter.
* @param {number} start The first zero-based index to include in the subset.
* @param {?number} end The non-inclusive last index of the subset.
* @return {object} mirrored array with mapped children
*/
function sliceChildren(children, start, end) {
if (children == null) {
return children;
}

var slicedChildren = {};
var flattenedMap = flattenChildren(children);
var ii = 0;
for (var key in flattenedMap) {
if (!flattenedMap.hasOwnProperty(key)) {
continue;
}
var child = flattenedMap[key];
// In this version of slice children we ignore empty children.
if (child !== null) {
if (ii >= start) {
slicedChildren[key] = child;
}
ii++;
if (end != null && ii >= end) {
break;
}
}
}
return slicedChildren;
}

module.exports = sliceChildren;

0 comments on commit d501485

Please sign in to comment.