solidjs-community / solid-codemod Goto Github PK
View Code? Open in Web Editor NEWCodemod scripts for SolidJS JavaScript library
License: MIT License
Codemod scripts for SolidJS JavaScript library
License: MIT License
import React, { useRef } from "react";
import { render } from "react-dom";
const Component = () => {
const ref = useRef();
useEffect(() => {
ref.current.style.color = "purple";
}, []);
return <div ref={ref}>Hello!</div>;
};
render(() => <Component />, document.getElementById("app"));
import { render } from "solid-js/web";
const Component = () => {
let ref;
useEffect(() => {
ref.style.color = "purple";
}, []);
return <div ref={ref}>Hello!</div>;
};
render(() => <Component />, document.getElementById("app"));
In addition to removing useRef
and replacing const
with let
, ideally we could remove the .current
suffix after every ref
.
A challenge is that ref
s shouldn't be passed into functions though; you'd need to wrap them in functions.
import React from "react";
function Component1({name, count}) {
return <div>Hello {name}! Count is {count}</div>;
}
function Component2({name, count, ...rest}) {
return <div {...rest}>Hello {name}! Count is {count}</div>;
}
render(() => <Component />, document.getElementById("app"));
import { splitProps } from "solid-js";
function Component1(props) {
return <div>Hello {props.name}! Count is {props.count}</div>;
}
function Component2(props) {
const [local, rest] = splitProps(props, ["name", "count"]);
return <div {...rest}>Hello {local.name}! Count is {local.count}</div>;
}
Related work on the Babel front:
actual tools to convert from react to solid
suid - A port of Material-UI (MUI) built with SolidJS.
suid/codemod - Transform your MUI React code to SUID SolidJS. (live demo)
solid-reactor - A compiler to ease the move from React to SolidJS.
react2solid - from scratch?
eslint-plugin-react2solid - based on eslint
some simple transforms are working
im currently working on React.useRef (#3) done
ideally mitosis would work better, then i would transform react โ mitosis โ solid
but i guess its hard to make that lossless
related
sveltosis - convert svelte to mitosis. parser based on svelte parser
component-party - Web component JS frameworks overview by their syntax and features
Here are the list of features from React that may not be possible to be converted into SolidJS code and their possible workarounds
react
cloneElement
- Probably Element.cloneNode
, but this highly depends on the usage and only works for DOM nodes not components.createFactory
isValidElement
- the lack of VDOM makes this impossible, however, instanceof Element
can be a valid workaround in some cases.createRef
- we can probably create a library shim such that this one exists and still returns the object, but we can convert those ref property usages into a callback assignment e.g. (el) => ref.current = el
.forwardRef
- Can be removed or provide a library shim, which ever works.memo
- There's already a memo
function in SolidJS but it behaves differently. We can remove this during compilation since it is totally unnecessary.useReducer
- provide a library shimuseRef
- we can remove this and change VariableDeclaration, but that also requires current
property accesses.useLayoutEffect
- I'm not sure if createRenderEffect
can replace this.useImperativeHandle
- library shimuseCallback
- can be removeduseDebugValue
- statement can be removed.useDeferredValue
- Now this one is highly different from createDeferred
. We'll probably need Ryan's consultation.useInsertionEffect
- I'm not sure what this is, but I believe it is discussed in the <style>
guide for React in the working groupuseSyncExternalStore
- library shimFragment
- library shim, but I think I've suggested Ryan to add this one into the SolidJS core.react-dom
findDOMNode
unmountComponentAtNode
- This one's impossible.flushSync
- not sure what this is for, probably for flushing updates.unstable_renderSubtreeIntoContainer
- I think this one was used in React Server Components, but given we don't have VDOM, this one's impossible.unstable_scheduleHydration
unstable_flushControlled
export const Looper = () => {
return <div>
{array.map(el => <div>{el.name}</div>)}
</div>;
}
import { For } from 'solid-js';
export const Looper = () => {
return <div>
<For each={array}>
{(el => <div>{el.name}</div>)}
</For>
</div>;
}
Here's a codemod which does this:
import {
ASTPath,
CallExpression,
FunctionExpression,
ImportDeclaration,
MemberExpression,
Transform,
} from 'jscodeshift';
const transform: Transform = (file, api, options) => {
const j = api.jscodeshift;
const root = j(file.source);
const importsRequired = new Set<string>();
// Replace JSX expression {<expression>.map(fn)} with <For each={expression}>{fn}</For>
root
.find(j.JSXExpressionContainer)
.filter(path => {
// We only care about JSX expression containers whose parents are JSX elements.
// (in other words, exclude attribute expressions.)
if (
path.parent.node.type === 'JSXElement' &&
path.node.expression.type === 'CallExpression'
) {
const call = path.node.expression;
if (
call.callee.type === 'MemberExpression' &&
call.callee.property.type === 'Identifier' &&
call.callee.property.name === 'map'
) {
return true;
}
}
return false;
})
.replaceWith(path => {
const call = path.node.expression as CallExpression;
const callee = call.callee as MemberExpression;
importsRequired.add('For');
return j.jsxElement.from({
openingElement: j.jsxOpeningElement(j.jsxIdentifier('For'), [
j.jsxAttribute.from({
name: j.jsxIdentifier('each'),
value: j.jsxExpressionContainer.from({
expression: callee.object,
}),
}),
]),
closingElement: j.jsxClosingElement(j.jsxIdentifier('For')),
selfClosing: false,
children: [
j.jsxExpressionContainer.from({
expression: call.arguments.at(0) as FunctionExpression,
}),
],
});
});
// See whether we need to add any imports
if (importsRequired.size > 0) {
// Look for solid-js import
let lastImport: ASTPath<ImportDeclaration> | null = null;
let solidImport = root
.find(j.ImportDeclaration)
.forEach(path => {
lastImport = path;
})
.filter(path => path.node.source.value === 'solid-js')
.forEach(path => {
if (!path.node.specifiers) {
path.node.specifiers = [];
}
path.node.specifiers?.forEach(spec => {
if (spec.type === 'ImportSpecifier') {
importsRequired.delete(spec.imported.name);
}
});
for (const symbol of importsRequired) {
path.node.specifiers.push(
j.importSpecifier.from({
imported: j.jsxIdentifier(symbol),
})
);
}
});
if (solidImport.length == 0) {
// Insert new solid import statement.
const solidImport = j.importDeclaration.from({
source: j.stringLiteral('solid-js'),
specifiers: Array.from(importsRequired).map(symbol =>
j.importSpecifier.from({
imported: j.jsxIdentifier(symbol),
})
),
});
lastImport!.insertAfter(solidImport);
}
}
return root.toSource({ quote: 'single' });
};
export default transform;
import React, { useState, useEffect } from "react";
import { render } from "react-dom";
const CountingComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
const interval = setInterval(() => setCount(count + 1), 1000);
return () => {
clearInterval(interval);
};
}, []);
return <div>Count value is {count}</div>;
};
render(() => <CountingComponent />, document.getElementById("app"));
import { createSignal, onCleanup, onMount } from "solid-js";
import { render } from "solid-js/web";
const CountingComponent = () => {
const [count, setCount] = createSignal(0);
onMount(() => {
const interval = setInterval(() => setCount(count + 1), 1000);
onCleanup(() => clearInterval(interval));
});
return <div>Count value is {count()}</div>;
};
render(() => <CountingComponent />, document.getElementById("app"));
Example transform to convert useState/useEffect of ReactJS to createSignal/onCleanup of SolidJS.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.