UNPKG

react-hookify

Version:

A CLI tool to convert React class components into functional components with hooks

213 lines (197 loc) 6.94 kB
const { getInsideOfFunc, validBraces, getInsideOfLifeCycle, } = require('../commonUtils') const { createCompDidMountLifeCycle } = require('./componentDidMountParse') const { createCompDidUpdateLifeCycle } = require('./componentDidUpdateParse') const { createCompWillUnmountLifeCycle, createCompWillUnmountCleanUp, } = require('./componentWillUnmountParse') //Loops through string and finds components-lifecycle-methods, //storing them in a object with the key being the name of thelifecycle method and the value being the code block function findComponents(string) { const componentTypes = [ 'componentDidMount(', 'componentDidUpdate(', 'componentWillUnmount(', ] const returnedComponents = {} for (let i = 0; i < componentTypes.length; i++) { const currentComponent = componentTypes[i] if (string.indexOf(currentComponent) !== -1) { let componentIndex = string.indexOf(currentComponent) let bracketIndex = string.indexOf('{', componentIndex) let componentEndIndex = bracketIndex + 1 let componentSlice = string.slice(bracketIndex, componentEndIndex) while (!validBraces(componentSlice)) { componentEndIndex++ componentSlice = string.slice(bracketIndex, componentEndIndex) } componentSlice = string.slice(componentIndex, componentEndIndex) returnedComponents[currentComponent + ')'] = componentSlice } } return returnedComponents } //Creates routes for creating useEffects, Checks for type of Lifecycle Method //Takes in object of lifecycle hooks, routes to different useEffect creatations function createUseEffects(objectOfLifeCycle) { const objectOfLifeCycleKeys = Object.keys(objectOfLifeCycle) if (objectOfLifeCycleKeys.length === 1) { let useEffect = createSingleUseEffect( objectOfLifeCycle[objectOfLifeCycleKeys[0]], objectOfLifeCycleKeys[0] ) let results = {} results[objectOfLifeCycleKeys[0]] = useEffect return results } else { // Mount and Update let similarities if ( objectOfLifeCycleKeys.includes('componentDidMount()') && objectOfLifeCycleKeys.includes('componentDidUpdate()') ) { similarities = checkMountAndUpdateForSimilarties(objectOfLifeCycle) } // Sends updated lifecycle object to be created into useEffect templates if (similarities === -1 || similarities === undefined) { return multiuseEffectCreate(objectOfLifeCycle) } else { return multiuseEffectCreate(similarities) } } } //Creates useEffect from body of lifecycle method that is passed in function createSingleUseEffect(string, method, cleanup) { if (method === 'componentDidMount()') { return createCompDidMountLifeCycle(string, method, cleanup) } else if (method === 'componentDidUpdate()') { return createCompDidUpdateLifeCycle(string, method) } else if (method === 'componentWillUnmount()') { return createCompWillUnmountLifeCycle(string, method) } } // Loops through object containing Lifecycle methods and creates useEffect function multiuseEffectCreate(object) { let results = {} let lifecycleObject = object if ( lifecycleObject['componentDidMount()'] && lifecycleObject['componentWillUnmount()'] ) { // Create cleanup temple const cleanup = createCompWillUnmountCleanUp( lifecycleObject['componentWillUnmount()'], 'componentWillUnmount()' ) const mountTemplate = createCompDidMountLifeCycle( lifecycleObject['componentDidMount()'], 'componentDidMount()', cleanup ) results['componentDidMount()'] = mountTemplate delete lifecycleObject['componentWillUnmount()'] delete lifecycleObject['componentDidMount()'] } // Creates useEffects for (let i in lifecycleObject) { const key = i const value = lifecycleObject[i] let useEffect = createSingleUseEffect(value, key) results[key] = useEffect } return results } //Finds similar lines in Mount and Update and updates lifecycle methods to be created into useEffects function checkMountAndUpdateForSimilarties(object) { const objectOfLifeCycleKeys = Object.keys(object) let componentDidMountBodyArray = [] if ( objectOfLifeCycleKeys.includes('componentDidMount()') && objectOfLifeCycleKeys.includes('componentDidUpdate()') ) { const componentDidMountbodyString = getInsideOfLifeCycle( object[objectOfLifeCycleKeys[0]], objectOfLifeCycleKeys[0] ) let bodyMountLineArray = componentDidMountbodyString.split(/\r?\n/) bodyMountLineArray = bodyMountLineArray.map((line) => { return line.trim() }) componentDidMountBodyArray = bodyMountLineArray if (objectOfLifeCycleKeys[1] === 'componentDidUpdate()') { const componentDidUpdatebodyString = getInsideOfLifeCycle( object[objectOfLifeCycleKeys[1]], objectOfLifeCycleKeys[1] ) let bodyUpdateLineArray = componentDidUpdatebodyString.split(/\r?\n/) bodyUpdateLineArray = bodyUpdateLineArray.map((line) => { return line.trim() }) for (let i = 0; i < bodyUpdateLineArray.length; i++) { const currentLine = bodyUpdateLineArray[i] const index = componentDidMountBodyArray.indexOf(currentLine) if (index > -1) { componentDidMountBodyArray = componentDidMountBodyArray.splice( index, 1 ) } } if (componentDidMountBodyArray.length === 0) { return -1 } else { bodyMountLineArray = bodyMountLineArray.map((line) => { if (bodyUpdateLineArray.indexOf(line.trim()) === -1) { return line + '\n' } }) if (bodyMountLineArray[0] !== undefined) { object['componentDidMount()'] = 'componentDidMount() {\n' + ` ${bodyMountLineArray.join(' ')}` + ' }' } else { delete object['componentDidMount()'] } return object } } } } function handleAsync(arrOfUseEffects) { for (let idx = 0; idx < arrOfUseEffects.length; idx++) { let useEffect = arrOfUseEffects[idx] if (useEffect.includes('await')) { let useEffectInnards = getInsideOfFunc(useEffect, 'useEffect') arrOfUseEffects[idx] = useEffect.replace( useEffectInnards, `(async () => {${useEffectInnards}})()` ) } } } function getUseEffects(bodyAsStr) { const initialLifecyclesObj = findComponents(bodyAsStr) const modifiedLifecyclesObj = createUseEffects(initialLifecyclesObj) const array = [] for (let key in modifiedLifecyclesObj) { if (Array.isArray(modifiedLifecyclesObj[key])) { array.push(...modifiedLifecyclesObj[key]) } else { array.push(modifiedLifecyclesObj[key]) } } // handleAsync(array); return array } module.exports = { findComponents, createSingleUseEffect, createUseEffects, handleAsync, getUseEffects, }