jridgewell / babel-plugin-transform-incremental-dom

Turn JSX into IncrementalDOM
MIT License
145 stars 12 forks source link

Problem when rendering jsx via function calls inside map/forEach #65

Closed mairatma closed 7 years ago

mairatma commented 8 years ago

Say you have some code like this:

function renderMessage(i) {
    return <em>{`my message ${i}`}</em>;
}

function render() {
    return (
        <ul>
            {
                [0, 1, 2, 3, 4].map(
                    i => <li>{renderMessage(i)}</li>
                )
            }
        </ul>
    );
}

IncrementalDOM.patch(element, render);

After patching the element the rendered contents should be a list with <li><em> items inside it, but are actually:

<ul>
  <em>my message 0</em>
  <em>my message 1</em>
  <em>my message 2</em>
  <em>my message 3</em>
  <em>my message 4</em>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

Looking at the compiled code it seems like this happens because the renderMessage function is called before its wrapping li, being passed to an inner function instead of being called inside it at the correct place:

    function render() {
        IncrementalDOM.elementOpen('ul');
        iDOMHelpers.renderArbitrary([0, 1, 2, 3, 4].map(function (i) {
            return iDOMHelpers.jsxWrapper(function (_renderMessage) {
                IncrementalDOM.elementOpen('li');
                iDOMHelpers.renderArbitrary(_renderMessage);
                return IncrementalDOM.elementClose('li');
            }, [renderMessage(i)]);
        }));
        return IncrementalDOM.elementClose('ul');
    }

It would be safer to always call functions like this inside the function wrapping it, instead of passing its return value as a param, to guarantee the order of incremental dom calls can happen as the developer expects.

cwouter commented 8 years ago

Is there any quick fix to bypass this issue?

jridgewell commented 8 years ago

Is there any quick fix to bypass this issue?

Inline it, or return an JSX element wrapped in an array from the helper.