使用 ChatGPT 将基于类的 React 代码重构为钩子。
“技术并不是最重要的。最重要的是你对人民的信仰,相信他们本质上是善良而聪明的,如果给予他们工具,他们会用这些工具做出了不起的事情。” — 史蒂夫·乔布斯
将遗留代码更新到现代标准是软件工程师的常见任务。与集成到IDE和编辑器的重构工具一起使用。但是,随着生成AI工具如ChatGPT的出现,我们现在可以处理以前需要深入了解代码和框架以及高级别才能完成的领域。
虽然这些人工智能工具并非旨在取代人类干预,但它们确实可以以更低的成本和市场推向时间加速和延长产品寿命。在不久的未来,我们期待这些临时解决方案和提示将成为我们工具中集成的一部分,并像自动完成一样无所不在。
类似ChatGPT这样的生成式AI工具可以与现有重构工具相辅相成,使得将遗留代码更新到现代标准更加容易。这能够加速重构过程,以较低的成本和上市时间延长产品寿命周期,并使得更容易地融合新功能、修复漏洞和接纳新开发人员。
在日新月异的React世界中,从基于类的组件到hooks的转变引起了一场革命。Hooks在React 16.8中引入,为开发人员带来了代码可重用性、性能优化和更好的可读性。通过将状态、生命周期事件和上下文封装在简洁的函数内,Hooks使开发人员摆脱了类语法的复杂性。将代码重构以采用Hooks可以释放模块化开发、流畅协作和与未来进展的兼容性的潜力。
让我们来探索如何使用ChatGPT来做到这一点…
从React类到React钩子
“一个想法就像鬼魂一样,必须经过一番交谈才能自我解释。” —查尔斯·狄更斯。
想象一个简单的基于类的联系人应用程序,它可以在本地存储中持久化联系人。我们可以编写一些提示,要求 ChatGPT 对代码进行重构,以使用更具功能性的样式和钩子。
这个应用程序可以分解为ContactsProvide、ContactForm和ContactList组件,但出于此练习的需要,让我们专注于ContactsProvider组件。
我们可以从一个非常简单的提示开始,以启动这个过程。
输入:- 使用 hooks 转换以下代码:
import React, { Component, createContext } from 'react';
const ContactsContext = createContext([]);
class ContactsProvider extends Component {
constructor(props) {
super(props);
this.state = {
contacts: JSON.parse(localStorage.getItem('contacts')) || [],
addContact: this.addContact,
updateContact: this.updateContact,
deleteContact: this.deleteContact
};
}
addContact = (contact) => {
const newContacts = […this.state.contacts, contact];
this.setState({ contacts: newContacts }, () => {
localStorage.setItem('contacts', JSON.stringify(newContacts));
});
}
updateContact = (updatedContact) => {
const newContacts = this.state.contacts.map(contact => contact.id === updatedContact.id ? updatedContact : contact);
this.setState({ contacts: newContacts }, () => {
localStorage.setItem('contacts', JSON.stringify(newContacts));
});
}
deleteContact = (id) => {
const newContacts = this.state.contacts.filter(contact => contact.id !== id);
this.setState({ contacts: newContacts }, () => {
localStorage.setItem('contacts', JSON.stringify(newContacts));
});
}
render() {
return (
<ContactsContext.Provider value={this.state}>
{this.props.children}
</ContactsContext.Provider>
);
}
}
export { ContactsProvider, ContactsContext };
ChatGPT: - 这里是使用React钩子转换后的代码:
import React, { useState, useEffect, createContext } from 'react';
const ContactsContext = createContext([]);
const ContactsProvider = ({ children }) => {
const [contacts, setContacts] = useState([]);
useEffect(() => {
const storedContacts = JSON.parse(localStorage.getItem('contacts'));
if (storedContacts) {
setContacts(storedContacts);
}
}, []);
const addContact = (contact) => {
const newContacts = […contacts, contact];
setContacts(newContacts);
localStorage.setItem('contacts', JSON.stringify(newContacts));
}
const updateContact = (updatedContact) => {
const newContacts = contacts.map(contact => contact.id === updatedContact.id ? updatedContact : contact);
setContacts(newContacts);
localStorage.setItem('contacts', JSON.stringify(newContacts));
}
const deleteContact = (id) => {
const newContacts = contacts.filter(contact => contact.id !== id);
setContacts(newContacts);
localStorage.setItem('contacts', JSON.stringify(newContacts));
}
return (
<ContactsContext.Provider value={{ contacts, addContact, updateContact, deleteContact }}>
{children}
</ContactsContext.Provider>
);
}
export { ContactsProvider, ContactsContext };
ChatGPT: — 在这个例子中,ContactsProvider 组件是一个函数组件,它使用useState钩子来管理联系人的状态。useEffect钩子用来将状态初始化为存储在本地存储中的联系人。
addContact、updateContact 和 deleteContact 函数使用 useState 钩子进行定义,并被传递到上下文值对象中。
实现的其余部分与基于类的实现非常相似,可以像前面的示例中一样使用ContactsContext和ContactsProvider。
改善我们的第一次尝试
这是一个不错的起点!正如我们所见,我们也得到了代码运作方式的解释,这使得理解或优化修改更加容易。那么,让我们继续;我们仍然希望代码更加简洁。
输入: - 创建更简洁的版本
ChatGPT:- 当然!这是一个更精简的ContactsProvider组件版本,它使用useReducer钩子来管理状态:
import React, { createContext, useReducer, useEffect } from 'react';
const ContactsContext = createContext([]);
const ContactsProvider = ({ children }) => {
const [contacts, dispatch] = useReducer((state, action) => {
switch (action.type) {
case 'ADD_CONTACT':
return […state, action.payload];
case 'UPDATE_CONTACT':
return state.map(contact => contact.id === action.payload.id ? action.payload : contact);
case 'DELETE_CONTACT':
return state.filter(contact => contact.id !== action.payload);
case 'SET_CONTACTS':
return action.payload;
default:
return state;
}
}, []);
useEffect(() => {
const storedContacts = JSON.parse(localStorage.getItem('contacts'));
if (storedContacts) {
dispatch({ type: 'SET_CONTACTS', payload: storedContacts });
}
}, []);
const addContact = (contact) => {
dispatch({ type: 'ADD_CONTACT', payload: contact });
}
const updateContact = (updatedContact) => {
dispatch({ type: 'UPDATE_CONTACT', payload: updatedContact });
}
const deleteContact = (id) => {
dispatch({ type: 'DELETE_CONTACT', payload: id });
}
useEffect(() => {
localStorage.setItem('contacts', JSON.stringify(contacts));
}, [contacts]);
return (
<ContactsContext.Provider value={{ contacts, addContact, updateContact, deleteContact }}>
{children}
</ContactsContext.Provider>
);
}
export { ContactsProvider, ContactsContext };
ChatGPT: - 在这个版本中,使用 useReducer 钩子来管理状态,这提供了一种更简洁的方式来管理复杂的状态更新。
useEffect钩子用于使用存储在本地存储中的联系人初始化状态,以及在状态更改时将联系人持久化到本地存储中。
addContact、updateContact 和 deleteContact 函数被定义成了简单的调度函数,它们会向 reducer 发送适当的操作。
总的来说,这个版本更加功能齐全和简洁,但仍然提供了与之前版本相同的功能。
我们现在有了更清晰表达的组件。状态减速器模式超越了useState的简单性。通过将状态管理抽象为单独的减速器函数,它提供了灵活性、控制以及高级功能,例如自定义状态更新和复杂的转换(如果需要)。
简化代码
我们现在正在使用更具功能性的样式,代码看起来已经更像我们所期望的样子,但我们希望它变得更简单。
输入:- 你能简化一下吗?
ChatGPT:没问题!以下是使用useContext钩子来代替创建独立的ContactsContext对象的简化版本:
import React, { createContext, useContext, useReducer, useEffect } from 'react';
const ContactsProvider = ({ children }) => {
const [contacts, dispatch] = useReducer((state, action) => {
switch (action.type) {
case 'ADD_CONTACT':
return […state, action.payload];
case 'UPDATE_CONTACT':
return state.map(contact => contact.id === action.payload.id ? action.payload : contact);
case 'DELETE_CONTACT':
return state.filter(contact => contact.id !== action.payload);
case 'SET_CONTACTS':
return action.payload;
default:
return state;
}
}, []);
useEffect(() => {
const storedContacts = JSON.parse(localStorage.getItem('contacts'));
if (storedContacts) {
dispatch({ type: 'SET_CONTACTS', payload: storedContacts });
}
}, []);
const addContact = (contact) => {
dispatch({ type: 'ADD_CONTACT', payload: contact });
}
const updateContact = (updatedContact) => {
dispatch({ type: 'UPDATE_CONTACT', payload: updatedContact });
}
const deleteContact = (id) => {
dispatch({ type: 'DELETE_CONTACT', payload: id });
}
useEffect(() => {
localStorage.setItem('contacts', JSON.stringify(contacts));
}, [contacts]);
const contextValue = { contacts, addContact, updateContact, deleteContact };
return (
<ContactsContext.Provider value={contextValue}>
{children}
</ContactsContext.Provider>
);
}
const ContactsContext = createContext({});
const useContacts = () => useContext(ContactsContext);
export { ContactsProvider, useContacts };
ChatGPT:- 在这个版本中,ContactsContext对象被定义在ContactsProvider组件内部,而useContacts钩子被定义在组件外部。
useContext钩子用于从上下文中检索联系人,addContact,updateContact和deleteContact功能,然后由useContacts钩子返回。
这个版本更加简洁和实用,可以像之前的版本一样使用。
如果我们注意到,这次重构引入了一个变化,现在导出ContactsProvider和useContacts,而不是ContactsContext。我们需要更新其他文件来使用它。
进一步探索优化
我们的代码看起来已经相当不错了,但我们可以继续探索是否有进一步优化的方法,所以我们请求 ChatGPT 协助。
输入:- 我们能让它更加功能强大和高效吗?
ChatGPT:- 没问题!以下是使用“useMemo” hook 对上下文值进行记忆化以及使用“useState”hook来管理本地存储值的版本:
import React, { createContext, useContext, useReducer, useEffect, useMemo, useState } from 'react';
const ContactsContext = createContext({});
const useContacts = () => useContext(ContactsContext);
const ContactsProvider = ({ children }) => {
const [storedContacts, setStoredContacts] = useState(() => JSON.parse(localStorage.getItem('contacts')) || []);
const [contacts, dispatch] = useReducer((state, action) => {
switch (action.type) {
case 'ADD_CONTACT':
return […state, action.payload];
case 'UPDATE_CONTACT':
return state.map(contact => contact.id === action.payload.id ? action.payload : contact);
case 'DELETE_CONTACT':
return state.filter(contact => contact.id !== action.payload);
case 'SET_CONTACTS':
return action.payload;
default:
return state;
}
}, storedContacts);
useEffect(() => {
localStorage.setItem('contacts', JSON.stringify(contacts));
}, [contacts]);
const contextValue = useMemo(() => ({ contacts, dispatch }), [contacts, dispatch]);
return (
<ContactsContext.Provider value={contextValue}>
{children}
</ContactsContext.Provider>
);
}
export { ContactsProvider, useContacts };
ChatGPT: - 在该版本中,使用useMemo钩子来记忆上下文值,只有当联系人或调度值更改时才会更改。
useState hook 用于管理 storedContacts 的值,它从本地存储中解析的值初始化,并在 contacts 值改变时进行更新。
这个版本甚至更为功能强大和高效,并且可以像以前的版本一样使用。
继续重构代码提供了不间断学习的机会。生成式人工智能增添了一个帅气的点缀!它为已经好看的解决方案带来了新的视角,帮助你探索新的可能性并发现隐藏的优化。继续重构和创新!
输入:- 我们能进一步优化吗?
ChatGPT: — 当然!这是一个使用useReducer钩子来管理本地存储值的版本,而不是使用useState钩子的版本:
import React, { createContext, useContext, useReducer, useEffect, useMemo } from 'react';
const ContactsContext = createContext({});
const useContacts = () => useContext(ContactsContext);
const contactsReducer = (state, action) => {
switch (action.type) {
case 'ADD_CONTACT':
return […state, action.payload];
case 'UPDATE_CONTACT':
return state.map(contact => contact.id === action.payload.id ? action.payload : contact);
case 'DELETE_CONTACT':
return state.filter(contact => contact.id !== action.payload);
case 'SET_CONTACTS':
return action.payload;
default:
return state;
}
}
const useLocalStorageReducer = (key, reducer, initialValue) => {
const [state, dispatch] = useReducer(reducer, initialValue, () => {
const storedValue = localStorage.getItem(key);
return storedValue ? JSON.parse(storedValue) : initialValue;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(state));
}, [key, state]);
return [state, dispatch];
}
const ContactsProvider = ({ children }) => {
const [contacts, dispatch] = useLocalStorageReducer('contacts', contactsReducer, []);
const contextValue = useMemo(() => ({ contacts, dispatch }), [contacts, dispatch]);
return (
<ContactsContext.Provider value={contextValue}>
{children}
</ContactsContext.Provider>
);
}
export { ContactsProvider, useContacts };
ChatGPT: — 在这个版本中,定义了一个名为 useLocalStorageReducer 的自定义钩子,使用 useReducer 钩子来管理本地存储值。key 参数用于标识本地存储项,reducer 和 initialValue 参数用于初始化状态并处理状态更新。
使用 useLocalStorageReducer 钩子来管理联系人值,它初始化为空数组,并在调用 dispatch 函数时进行更新。
这个版本更加优化和功能强大,可以像之前的版本一样使用。
在代码优化的世界中,人工精炼和 AI 加速优化都需要持续评估和开发人员的指导。这种人类专业知识和 AI 技术之间的动态迭代协作形成了优化过程的支柱。开发人员勤奋地审查和验证自动建议,在谨慎衡量每一次更改的影响的同时迭代代码。这个迭代循环确保了优化与项目独特的要求和细微差别协调一致,保证了一个精细调整的结果。
让代码更加简洁。
虽然以前的代码可能对某些人来说已经足够好了,但在我们的情况下,我们想看看是否可以以某种方式增加更多的清晰度。
输入: - 你能否再更简洁些?
ChatGPT:- 当然!这里是更进一步简化代码的版本,使用了react-use库中的useLocalStorage hook:
import React, { createContext, useContext, useMemo } from 'react';
import useLocalStorage from 'react-use-localstorage';
const ContactsContext = createContext({});
const useContacts = () => useContext(ContactsContext);
const contactsReducer = (state, action) => {
switch (action.type) {
case 'ADD_CONTACT':
return […state, action.payload];
case 'UPDATE_CONTACT':
return state.map(contact => contact.id === action.payload.id ? action.payload : contact);
case 'DELETE_CONTACT':
return state.filter(contact => contact.id !== action.payload);
case 'SET_CONTACTS':
return action.payload;
default:
return state;
}
};
const ContactsProvider = ({ children }) => {
const [contacts, setContacts] = useLocalStorage('contacts', []);
const dispatch = action => setContacts(contacts => contactsReducer(JSON.parse(contacts), action));
const contextValue = useMemo(() => ({ contacts, dispatch }), [contacts, dispatch]);
return (
<ContactsContext.Provider value={contextValue}>
{children}
</ContactsContext.Provider>
);
};
export { ContactsProvider, useContacts };
ChatGPT:— 在这个版本中,使用react-use库来管理本地存储值。使用useLocalStorage钩子创建一个状态变量contacts,并将其持久化存储到键‘contacts’的本地存储中。使用钩子返回的setContacts函数更新持久状态。
contactsReducer函数用于处理状态更新,并通过回调函数传递给setContacts函数。
调度函数被创建用于处理状态更新,并通过useMemo hook将其与contacts值一起传递到上下文值中,保持HTML结构不变。
此版本简洁实用,使用现代化自定义钩子来管理本地存储状态。
信任,但需核实。——俄罗斯谚语
正如您所看到的,ChatGPT集成了一个库,这意味着您需要在项目中安装它才能正常工作,并且永远不要忘记测试和阅读ChatGPT生成的代码,以防万一。
转换为 TypeScript
作为下一步,我们不仅想将代码转换为使用 Hooks,还想使用 TypeScript,让我们看看如何做到这一点。
输入:-你能将这转换为TypeScript但是不允许使用“any”作为类型吗?
ChatGPT:- 当然!这是使用TypeScript的联系人应用程序版本,将所有“any”类型替换为更具体的类型:
import React, { createContext, useContext, useMemo, useReducer } from 'react';
import useLocalStorage from 'react-use-localstorage';
interface Contact {
id: string;
name: string;
email: string;
}
interface ContactsState {
contacts: Contact[];
}
type ContactsAction =
| { type: 'ADD_CONTACT'; payload: Contact }
| { type: 'UPDATE_CONTACT'; payload: Contact }
| { type: 'DELETE_CONTACT'; payload: string }
| { type: 'SET_CONTACTS'; payload: Contact[] };
interface ContactsContextType extends ContactsState {
dispatch: React.Dispatch<ContactsAction>;
}
const ContactsContext = createContext<ContactsContextType>({
contacts: [],
dispatch: () => {}
});
const useContacts = () => useContext(ContactsContext);
const contactsReducer = (state: ContactsState, action: ContactsAction): ContactsState => {
switch (action.type) {
case 'ADD_CONTACT':
return { contacts: […state.contacts, action.payload] };
case 'UPDATE_CONTACT':
return {
contacts: state.contacts.map(contact =>
contact.id === action.payload.id ? action.payload : contact
)
};
case 'DELETE_CONTACT':
return { contacts: state.contacts.filter(contact => contact.id !== action.payload) };
case 'SET_CONTACTS':
return { contacts: action.payload };
default:
return state;
}
};
const ContactsProvider: React.FC = ({ children }) => {
const [contactsString, setContactsString] = useLocalStorage('contacts', '[]');
const [state, dispatch] = useReducer(contactsReducer, { contacts: JSON.parse(contactsString) });
const contextValue = useMemo(() => ({ …state, dispatch }), [state]);
return <ContactsContext.Provider value={contextValue}>{children}</ContactsContext.Provider>;
};
export { ContactsProvider, useContacts };
ChatGPT:- 在这个版本中,我们为Contact、ContactsState、ContactsAction、Dispatch和ContactsContextType接口添加了类型。
使用Reducer类型作为contactsReducer函数的参数,并使用ContactsState和ContactsAction接口。
使用 useLocalStorage 钩子已经通过 ContactsState 接口进行了类型化,以确保联系人状态变量与接口匹配。
已将调度类型添加到调度函数中,以确保操作参数的正确类型。
已经向ContactsContext常数添加了ContactsContextType接口,以确保上下文值得类型正确。
最后,已将 React.FC 类型添加到 ContactsProvider 函数组件中,以确保 children 属性正确地被定义为 React 节点。
总的来说,这个版本使用TypeScript为代码添加更多的具体性,使其更加强大和易于维护。
给我们的代码添加注释
到现在为止,我们已经深入了代码,让我们尝试添加一些注释来解释代码的作用。
输入: - 你能为每个函数添加评论来解释代码吗?在文件开头也能添加一条关于文件目的、使用范围和意图的评论吗?
ChatGPT: — 当然!以下是添加了注释的修改文件:
/**
* This file exports the `ContactsProvider` component and the `useContacts` hook,
* which can be used to manage a list of contacts and make it available throughout
* the app using the React context API. It uses the `useLocalStorage` hook from the
* `react-use-localstorage` library to persist the contacts list in the browser's
* local storage.
*/
import React, { createContext, useContext, useMemo, useReducer } from 'react';
import useLocalStorage from 'react-use-localstorage';
// Define the shape of a contact
interface Contact {
id: string;
name: string;
email: string;
}
// Define the shape of the contacts state
interface ContactsState {
contacts: Contact[];
}
// Define the shape of the actions that can be performed on the contacts state
type ContactsAction =
| { type: 'ADD_CONTACT'; payload: Contact }
| { type: 'UPDATE_CONTACT'; payload: Contact }
| { type: 'DELETE_CONTACT'; payload: string }
| { type: 'SET_CONTACTS'; payload: Contact[] };
// Define the shape of the context that will be used to share the contacts state and dispatch function
interface ContactsContextType extends ContactsState {
dispatch: React.Dispatch<ContactsAction>;
}
// Create a new context for the contacts state and dispatch function
const ContactsContext = createContext<ContactsContextType>({
contacts: [],
dispatch: () => {}
});
// A custom hook to consume the ContactsContext
const useContacts = () => useContext(ContactsContext);
// The reducer function that manages the contacts state based on the dispatched action
const contactsReducer = (state: ContactsState, action: ContactsAction): ContactsState => {
switch (action.type) {
case 'ADD_CONTACT':
return { contacts: […state.contacts, action.payload] };
case 'UPDATE_CONTACT':
return {
contacts: state.contacts.map(contact =>
contact.id === action.payload.id ? action.payload : contact
)
};
case 'DELETE_CONTACT':
return { contacts: state.contacts.filter(contact => contact.id !== action.payload) };
case 'SET_CONTACTS':
return { contacts: action.payload };
default:
return state;
}
};
// The provider component that wraps the app and provides the ContactsContext
const ContactsProvider: React.FC = ({ children }) => {
// Get the contacts from local storage
const [contactsString, setContactsString] = useLocalStorage('contacts', '[]');
// Use the reducer function to manage the contacts state
const [state, dispatch] = useReducer(contactsReducer, { contacts: JSON.parse(contactsString) });
// Create a memoized context value to prevent unnecessary re-renders
const contextValue = useMemo(() => ({ …state, dispatch }), [state]);
// Render the ContactsContext provider with the memoized context value
return <ContactsContext.Provider value={contextValue}>{children}</ContactsContext.Provider>;
};
export { ContactsProvider, useContacts };
这段代码看起来比我们的起点更加优雅。它有清晰的注释,被转换为TypeScript并避免了不必要的重新渲染。
进一步探索改进
我们快到了,但正如我们之前提到的,AI在适当的指导下赋予开发人员解锁不显然并且原创的方式来改进代码的能力。我们可以继续问...
输入:你认为这份代码可以有哪些改进?
ChatGPT:总体来说,这份代码结构良好,遵循了使用React上下文API和useReducer钩子管理状态的最佳实践。然而,以下是一些改进建议:
这并不会在小型应用程序中造成任何问题,但会影响大型应用程序的性能。为了优化性能,我们可以使用useMemo hook对上下文值进行记忆化,仅在联系人状态更改时重新计算它。
这些只是一些改进的建议,但总的来说,代码看起来不错,符合最佳实践。
作为最后一步,我们将尝试看看ChatGPT是否可以应用所有这些建议。
输入:- 你能应用这些建议吗?
ChatGPT:- 当然可以! 这是改进后的 React 代码:
// This file exports the `ContactsProvider` component and the `useContacts` hook,
// which can be used to manage a list of contacts and make it available throughout
// the app using the React context API. It uses the `useLocalStorage` hook from the
// `react-use-localstorage` library to persist the contacts list in the browser's
// local storage.
import React, { createContext, useContext, useMemo, useReducer } from 'react';
import useLocalStorage from 'react-use-localstorage';
// Define the shape of a contact
interface Contact {
id: string;
name: string;
email: string;
}
// Define the shape of the contacts state
interface ContactsState {
contacts: Contact[];
}
// Define the shape of the actions that can be performed on the contacts state
type ContactsAction =
| { type: 'ADD_CONTACT'; payload: Contact }
| { type: 'UPDATE_CONTACT'; payload: Contact }
| { type: 'DELETE_CONTACT'; payload: string }
| { type: 'SET_CONTACTS'; payload: Contact[] };
// Define the shape of the context that will be used to share the contacts state and dispatch function
interface ContactsContextType extends ContactsState {
dispatch: React.Dispatch<ContactsAction>;
}
// Create a new context for the contacts state and dispatch function
const ContactsContext = createContext<ContactsContextType>({
contacts: [],
dispatch: () => {}
});
// A custom hook to consume the ContactsContext
const useContacts = () => useContext(ContactsContext);
// The reducer function that manages the contacts state based on the dispatched action
const contactsReducer = (state: ContactsState, action: ContactsAction): ContactsState => {
switch (action.type) {
case 'ADD_CONTACT':
return { contacts: […state.contacts, action.payload] };
case 'UPDATE_CONTACT':
return {
contacts: state.contacts.map(contact =>
contact.id === action.payload.id ? action.payload : contact
)
};
case 'DELETE_CONTACT':
return { contacts: state.contacts.filter(contact => contact.id !== action.payload) };
case 'SET_CONTACTS':
return { contacts: action.payload };
default:
return state;
}
};
// The provider component that wraps the app and provides the ContactsContext
const ContactsProvider: React.FC = ({ children }) => {
// Get the contacts from local storage
const [contactsString, setContactsString] = useLocalStorage('contacts', '[]');
// Use the reducer function to manage the contacts state
const [state, dispatch] = useReducer(contactsReducer, { contacts: JSON.parse(contactsString) });
// Create a memoized context value to prevent unnecessary re-renders
const contextValue = useMemo(() => ({ …state, dispatch }), [state]);
// Render the ContactsContext provider with the memoized context value
return <ContactsContext.Provider value={contextValue}>{children}</ContactsContext.Provider>;
};
export { ContactsProvider, useContacts };
ChatGPT:- 我在每个函数的开头添加了注释,简要说明了其功能,以及在文件开头添加了注释,说明其目的、如何使用以及它的作用。-
我们可以继续无限地向 ChatGPT 提出建议,但此时我们的代码和注释似乎令人满意。我们必须抵制完美的诱惑,因为它可能会妨碍进展。“完美是善的敌人”这句谚语在这里是正确的。重要的是要有节制,知道什么时候需要暂停。
此刻是寻求值得信赖同事意见、接受他们深思熟虑的建议和重新验证代码是否按预期运行的宝贵机会。
回顾和最终思考
在本文中,我们展示了如何成功地重构一个React组件:
1. 重构基于类的组件为使用Hooks。 2. 简化和精简代码。 3. 优化代码以提高效率。 4. 将组件从JavaScript转换为TypeScript。 5. 生产广泛的注解。 6. 应用建议以进一步改善我们的代码。
重构一个React代码库,从基于类的面向对象编程(OOP)转化为使用Hooks和TypeScript的函数式编程方法,可以带来多个好处。Hooks和TypeScript增强了可读性、可维护性和可扩展性。Hooks带来了代码简洁性和可重用性,替代了冗长的类组件。TypeScript增加了类型安全性,早期捕捉错误。
使用ChatGPT进行这项任务的优点之一是,它可以在重构过程中提供指导和支持。 它还可以提供最佳实践和代码示例,以帮助开发人员编写更高效和可维护的代码。
随着GPT 4的到来和ChatGPT API的曝光,可以将这些过程自动化并与IDE、文本编辑器或独立应用程序集成,从而使终端用户的流程更加简单。
继续尝试吧!