React, TypeScript, and follow up contributions
Tags: opensource, react, chatgpt, typescript
Published: 2023-12-14 14:14:28

---
series: Contributing to ChatCraft
---

I am continuing my open source contributions to the [ChatCraft](https://github.com/tarasglek/chatcraft.org) project, a developer-oriented version of ChatGPT. This is the second issue I worked on. Despite it being a one line code change, this issue took me longer to fix than the last one.

# Issue Link
https://github.com/tarasglek/chatcraft.org/issues/307

# Issue Description
Clear stored API key when user changes the provider in the User Settings.

![User Settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efzlnp25vjqrgkgonl9a.png)

---

# Identifying the file or area of code to work on

By searching for `User Settings` in VSCode, I found User Settings form in the `PreferencesModel.tsx` file. 

![onChange event handler](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jhiqi3gaotxjhyhegdaa.png)

I was then able to locate the `Select` element responsible for the API URL dropdown. Then I was able to locate the onChange event handler for that dropdown. See React [forms](https://legacy.reactjs.org/docs/forms.html) official documentation.

Next, I identified the form element which displayed the API key, since we will need to clear that field.

![api key field](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/crol7du41ktjn2ofb01x.png)

---

# Understanding the code

I needed to understand the code, so that I could understand where the API key was stored and how to clear it. Not only do I need to clear the key from being displayed in the input field, but I also need to make sure it is cleared from storage.

I had never worked with TypeScript or [React forms](https://legacy.reactjs.org/docs/forms.html) before, so this took quite some time.

What helped me speed up the process was taking a close look at how existing functionalities were working.

### API key field onChange event handler

This changes our stored API key.

![api key field](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38mj8pdyz631loxlmiuc.png)

![api key field code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ftyejcz5r549ij0te5v8.png)

### Remove button onClick event handler

This clears our stored API key. This is what I need to get done!

![remove button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yu29kxtuozi5ajxsk1l5.png)

![remove button code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j250zidxzrjewy704t23.png)

By taking a look at these events, I learned that the settings were saved using the [`useContext` React hook](https://react.dev/reference/react/useContext).

![setSettings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2v6i9fj9q5ktcjqmdwcq.png)

From `src/hooks/use-settings:`

![use-settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fa4x5ns4kz63844v7s3a.png)

I can also see that the stored data is saved to LocalStorage:

![code for localstorage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0czwk7odlx6sh4ljc254.png)

A quick look with Dev Tools was enough to ascertain that fact:

![localstorage dev tools](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4boc253s21d13uxeck6.png)

---

# Coding and troubleshooting

It seemed like all I needed to do was use the same code from the Remove onClick handler inside my `Select` element onChange handler, in order to clear the data. However, the following code introduced issues:

```
<Select
  value={settings.apiUrl}
  onChange={(e) => setSettings({ ...settings, apiKey: undefined })}
>
```

Yes, it cleared the `apiKey`; however it no longer set the `apiUrl` to the newly selected value. This was a problem. I tried to query the html page element and set it directly, but this did not work because the `Select` element value was always going to display the stored `apiUrl` value. So I needed to set the value of the `apiUrl`

Eventually, I realized I could set both `apiUrl` and `apiUrl` elements at once.

![code changes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jps4z0k3six86n16uq79.png)

---

# Testing

![testing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xy9ed5jgcm8w2de0wl9e.png)

---

## Pull Request

{% embed https://github.com/tarasglek/chatcraft.org/pull/308 %}

My PR has been merged!

---

# ChatCraft Contribution Results

I met most of the goals I set out in my first post of this series,  mainly:

### Working with a language and framework that I had not recently contributed to

I had never worked extensively with TypeScript or React in the open source community.

### Working in an active project

I communicated to repo administrators and past contributors to troubleshoot linting issues, clarify requirements, implement code review fixes

### Adding a previously missing functionality and enhancing the end-user experience

1) Prior to my code changes, the end-user would still be taken to the chat page even if they entered an invalid OpenRouter key. They would not be notified that their key was invalid until they sent their first ChatCraft ChatGPT message.

![ChatCraft error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dz21szonf0xp2qj6wnlg.png)

Now, they would be notified with an error message when they try to Save/Submit their invalid key.

![OpenRouter key validation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xcyj3ftzss70mck7fnzt.png)

2) Prior to my code changes, the end-user would be sending their stored API key to the wrong provider the moment they try to switch providers in User Settings. I.e. when they have a stored OpenRouter API key, and they switch the provider to OpenAI, the stored key is automatically sent. This is not secure and we should not be sending sensitive data like an API key to the other provider. In addition, the user gets bombarded with connection error popup messages, which does not make for a good user experience.

![previous change provider behaviour](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/05euf9bmgdpebbcz8c8r.png)

Now, the moment they toggle the provider, the result is the key is cleared (same behaviour as the Remove button), and they can then input their new key.

![prompt for new key](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tt1jwbitqb66efy32rpo.png)

![cleared from localStorage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vb9jr6lgoqb9k5sxsur9.png)

### Fixing multiple issues that are related

One [PR](https://github.com/tarasglek/chatcraft.org/pull/308) has been merged and [another](https://github.com/tarasglek/chatcraft.org/issues/230) is awaiting code review after I made requested changes.

There is also another future issue I could work on:

Storing both OpenRouter and OpenAI keys separately, with no need to clear it when we select a different provider

### Conclusion

Because I ran out of time, I regret that I had not enough time to work on a larger feature. However, I believe I did well on branching out and working on a new project that was active and unfamiliar to me. This allowed me to collaborate and communicate with classmates and repo administrators. I also learned about calling the [OpenRouter API](https://openrouter.ai/docs#limits), and about [React forms](https://legacy.reactjs.org/docs/forms.html) and [React hooks](https://legacy.reactjs.org/docs/hooks-reference.html). This would not have been possible if I stuck with the previous project I was on.

I highly recommend to exploring multiple projects at the same time when contributing to open source! I have checked out many different project repos, and many times my PRs or comments on issues were not replied to, so it takes some time to find an active repo. Sometimes it is not about which project you most want to work on, but which ones want you! It is difficult to continue to build upon your contributions on a project if each pull request takes months to be reviewed. Moreover, it is important to be able to get in touch with repo admin to clarify methods or requirements. Best to check out a bunch and see which ones get back to you! Also, a good way to gauge the activeness of a repo is by using the Insights tab of GitHub, or asking people you know who have first-hand experience.