Skip to content

Instantly share code, notes, and snippets.

@iainbeeston
Created July 21, 2017 11:48
Show Gist options
  • Save iainbeeston/20800ecbda4602092b9e435e99452cb5 to your computer and use it in GitHub Desktop.
Save iainbeeston/20800ecbda4602092b9e435e99452cb5 to your computer and use it in GitHub Desktop.
Re-define react event handler methods using arrow functions
#!/usr/bin/env ruby
#
# Given some react components written as ES6 classes, this converts any event handler methods from "normal"
# class methods to be arrow functions, assigned to static variables in the class. That way the method is
# always bound to "this".
#
file_paths = ARGV
BIND_REGEXP = /this\.(\w+)\.bind\(this\)/
CALL_PROP_REGEXP = /=\{\s*\((.*?)\)\s*=>\s*\{?\s*(\w+)\(\1\)\s*\}?\s*\}/
ANON_FUNC_REGEXP = /=\{\s*\((.*?)\)\s*=>\s*\{?\s*this\.(\w+)\(\1\)\s*\}?\s*\}/
def replace_bind_with_arrow(contents)
contents.scan(BIND_REGEXP).uniq.each do |(callback_fn)|
method_found = !!contents.sub!(/#{callback_fn}\s*\((.*?)\)\s*\{/, "#{callback_fn} = (\\1) => {")
if method_found
contents.gsub!("this.#{callback_fn}.bind(this)", "this.#{callback_fn}")
else
class_name = contents[/class (\w+)/, 1]
puts "Could not find definition of #{class_name}.#{callback_fn}() to rewrite using an arrow function"
end
end
contents
end
def call_prop_directly(contents)
contents.scan(CALL_PROP_REGEXP).uniq.each do |(prop_fn)|
contents.gsub!(/=\{\s*\((.*?)\)\s*=>\s*\{?\s*#{prop_fn}\(\1\)\s*\}?\s*\}/, "={#{prop_fn}}")
end
contents
end
def replace_anon_funcs_with_arrow(contents)
contents.scan(ANON_FUNC_REGEXP).uniq.each do |(_args, anon_fn)|
method_found = !!contents.sub!(/#{anon_fn}\s*\((.*?)\)\s*\{/, "#{anon_fn} = (\\1) => {")
if method_found
contents.gsub!(/=\{\s*\((.*?)\)\s*=>\s*\{?\s*this\.#{anon_fn}\(\1\)\s*\}?\s*\}/, "={this.#{anon_fn}}")
else
class_name = contents[/class (\w+)/, 1]
puts "Could not find definition of #{class_name}.#{anon_fn}() to rewrite using an arrow function"
end
end
contents
end
file_paths.each do |path|
throw "Invalid path #{path}" unless File.exist?(path)
contents = File.read(path)
updated_contents = replace_anon_funcs_with_arrow(call_prop_directly(replace_bind_with_arrow(contents)))
File.write(path, updated_contents)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment