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

cannot replace JSX nodes within render props #565

Open
json2d opened this issue Jul 31, 2023 · 0 comments
Open

cannot replace JSX nodes within render props #565

json2d opened this issue Jul 31, 2023 · 0 comments

Comments

@json2d
Copy link

json2d commented Jul 31, 2023

i'm having a problem w/ replacing JSX nodes within render props:

https://astexplorer.net/#/gist/870412de2b8bc7bfd6bfa04cd4600680/381203659283e923155a6b62ed4739df11ba0c2d

input:

const MyController = (props) => (
  <Controller
    render={() => (
      <div id="inner" />
    )} 
  />
)

expected output:

const MyController = (props) => (
  <Controller
    render={() => (
     <div id="outer">
        <div id="inner" />
     </div>
    )} 
  />
)

v0.11.0 actual output:

const MyController = (props) => (
  <Controller
    render={() => (
      (<div id="inner" />)
    )} 
  />
)

v0.15.0 actual output:
[input was unmodified]

codemod:

module.exports = function (file, api) {
  const j = api.jscodeshift;
  const root = j(file.source);

  // Find all JSX elements with the name 'Controller'
  const controllerPaths = root.findJSXElements("Controller");

  // Process the found JSX elements
  controllerPaths.forEach((path) => {

    const renderAttribute = path.node.openingElement.attributes.find(
      (attr) => attr.name.name === "render"
    );

    if (
      renderAttribute &&
      renderAttribute.value.type === "JSXExpressionContainer" &&
      renderAttribute.value.expression.type === "ArrowFunctionExpression"
    ) {
      // Find the first JSXElement within the ArrowFunctionExpression
      const renderFunctionBodyNode = renderAttribute.value.expression.body;

      if (renderFunctionBodyNode) {

        const idAttribute = j.jsxAttribute(
          j.jsxIdentifier("id"),
          j.jsxExpressionContainer(j.identifier("outer"))
        );
        // Create a new JSXElement with div as its opening element
        const wrappedRenderFunctionBodyNode = j.jsxElement(
          j.jsxOpeningElement(j.jsxIdentifier("div"), [idAttribute]),
          j.jsxClosingElement(j.jsxIdentifier("div")),
          [renderFunctionBodyNode]
        );

        // Replace the existing JSXElement with the new one
        const renderFunctionBodyPaths = j(renderFunctionBodyNode);
        const renderFunctionBodyPath = renderFunctionBodyPaths.get(0);
        
        renderFunctionBodyPath.replace(wrappedRenderFunctionBodyNode)
      }
    }
  });

  return root.toSource();
};

is the codemod doing something wrong or is this a bug?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant