Function name is updated:
export {
- foo
+ bar
}
Find and replace 💪
import {
- foo
+ bar
} from './myLib.js'
// ...
- foo()
+ bar()
No access to the semantics of your code:
import { foo as fooA } from './myLib.js'
import { foo as fooB } from './otherLib.js'
obj.foo = 42
sendMessage('foo')
Binding manually:
class MyComponent extends React.Component {
constructor() {
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState({ open: true })
}
}
Using arrow function as class property:
class MyComponent extends React.Component {
handleClick = () => this.setState({ open: true })
}
Modify the program instead of text!
class MyComponent extends React.Component {
constructor() {
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState({ open: true })
}
}
MyComponent
constructor
=
this.handleClick
bind()
handleClick
setState()
Tools using the AST:
export default function transform(file, api) {
const j = api.jscodeshift
const root = j(file.source)
// ...transform root
return root.toSource()
}
State assignment in constructor:
class MyComponent extends React.Component {
constructor() {
this.state = {
foo: 'hello',
bar: 42
}
}
}
State as class property:
class MyComponent extends React.Component {
state = {
foo: 'hello',
bar: 42
}
}
export default function transform(file, api) {
const j = api.jscodeshift
const root = j(file.source)
root
.find(j.ClassDeclaration)
.find(j.MethodDefinition, { kind: 'constructor' })
.find(j.AssignmentExpression, {
left: {
object: j.ThisExpression,
property: { name: 'state' }
}
})
.forEach(stateAssignment => {
const initialState = stateAssignment.node.right
const asProperty = j.classProperty(j.identifier('state'), initialState, null, false)
j(stateAssignment)
.closest(j.ClassBody)
.get('body')
.insertAt(0, asProperty)
j(stateAssignment).remove()
})
return root.toSource()
}
Almost what we wanted:
class MyComponent extends React.Component {
state = {
foo: 'hello',
bar: 42
}
constructor() {}
}
git diff
check