Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat) - replaceNode parameter #1557

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,27 @@ import options from './options';
* @param {import('./internal').PreactElement} parentDom The DOM element to
JoviDeCroock marked this conversation as resolved.
Show resolved Hide resolved
* render into
*/
export function render(vnode, parentDom) {
export function render(vnode, parentDom, replaceNode) {
if (options.root) options.root(vnode, parentDom);
let oldVNode = parentDom._prevVNode;
vnode = createElement(Fragment, null, [vnode]);

let mounts = [];
diffChildren(parentDom, parentDom._prevVNode = vnode, oldVNode, EMPTY_OBJ, parentDom.ownerSVGElement!==undefined, oldVNode ? null : EMPTY_ARR.slice.call(parentDom.childNodes), mounts, vnode, EMPTY_OBJ);
diffChildren(
parentDom,
replaceNode ? vnode : (parentDom._prevVNode = vnode),
replaceNode ? undefined : oldVNode,
EMPTY_OBJ,
parentDom.ownerSVGElement !== undefined,
replaceNode
? [replaceNode]
: oldVNode
? null
: EMPTY_ARR.slice.call(parentDom.childNodes),
mounts,
vnode,
replaceNode || EMPTY_OBJ
);
commitRoot(mounts, vnode);
}

Expand Down
40 changes: 40 additions & 0 deletions test/browser/render.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -966,4 +966,44 @@ describe('render()', () => {

expect(scratch.textContent).to.equal('01');
});

describe('replaceNode parameter', () => {

function appendChildToScratch(id) {
const child = document.createElement('div');
child.id = id;
scratch.appendChild(child);
}

beforeEach(() => {
['a', 'b', 'c'].forEach(id => appendChildToScratch(id));
});

it('should use replaceNode as render root and not inject into it', () => {
const childA = scratch.querySelector('#a');
render(<div id="a">contents</div>, scratch, childA);
expect(scratch.querySelector('#a')).to.equal(childA);
expect(childA.innerHTML).to.equal('contents');
});

it('should not remove siblings of replaceNode', () => {
const childA = scratch.querySelector('#a');
render(<div id="a" />, scratch, childA);
expect(scratch.innerHTML).to.equal('<div id="a"></div><div id="b"></div><div id="c"></div>');
});

it('should render multiple render roots in one parentDom', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is so good 👍 💯

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

const childA = scratch.querySelector('#a');
const childB = scratch.querySelector('#b');
const childC = scratch.querySelector('#c');
const expectedA = '<div id="a">childA</div>';
const expectedB = '<div id="b">childB</div>';
const expectedC = '<div id="c">childC</div>';
render(<div id="a">childA</div>, scratch, childA);
render(<div id="b">childB</div>, scratch, childB);
render(<div id="c">childC</div>, scratch, childC);
expect(scratch.innerHTML).to.equal(`${expectedA}${expectedB}${expectedC}`);
});
});

});