how to Cook👩‍🍳Spoonacular API with React, Redux and also Mui & how to hack 🐱‍💻 API
Tags: react, javascript, api, webdev
Published: 2022-02-03 10:15:13

### What? Cooking?🧐

guys I just said😁, this is not a post for cooking.
 
I just said, this is not a cooking post.

This project is about how to make a Responsive Website in React-JS using Spoonacular API...


---

### Link to Code:✨

**GitHub**

{% github https://github.com/jacksonkasi0/cooking-time %}

**Website  Link:** [Cooking Time 👩‍🍳](https://cooking-time.netlify.app)


---


### Ok, but what about API Hack🐱‍💻?

spoonacular api free account 150 points / day


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4kpivbu7yztm5km4sw6.png)

So we can do nothing with spoonacular api if we run out of 150 points a day.

Trying so will throw `4️⃣0️⃣2️⃣ error❌`.

So to overcome this we have written a little code using redux.

Let me explain about that.

---

### let's break the limit ⚡

first this is my .env file:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0pwdygsbhuhsi3q25f8.png)


this is **index.js**


```javascript
    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import { BrowserRouter as Router } from "react-router-dom";
    import {createStore,combineReducers} from 'redux'
    import { Provider } from "react-redux";
    import changeRecipe from "./store/reducer/recipeId";
    import changeAPiKey from "./store/reducer/updateApi"
    
    
    //  store
    const rootReducer = combineReducers({
      recipeId_Data:changeRecipe,
      apiKey_Data:changeAPiKey,
    }) 
    const store = createStore(rootReducer)
    
    
    ReactDOM.render(
      <React.StrictMode>
        <Provider store={store} >
        <Router>
          <App />
        </Router>
        </Provider>
      </React.StrictMode>,
      document.getElementById('root')
    );
   ``` 


Since we use two different reducer here, we have set the variables to **rootReducer** using **combineReducers**.

One of the reducers is the API Key that we are going to look at now.
That's **changeAPiKey**.

If you already know about **redux**, I would not say more about redux.

But don't worry!!! Tell me if you want to know about redux, I will post as clearly as I can.
 

---

Well, we will now look at the action and reducer for changeAPiKey in the store.

**src / store / action / updateApi.js**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t16r0pe2lwtiy7psfutu.png)

**src / store / reducer / updateApi.js**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnslwg068ph8y2ydzb26.png)

What you need to notice in the reducer for the API Key is that I have set the first apikey in the .env file to **initialApiKey**.

```javascript
     const initialApiKey = {
       apiKey:process.env.REACT_APP_FOOD_API_KEY,
     };
```

We have written action & reducer for API Key.

OK. We will see how to use the api keys in .env.

---

**src / api / ApiKeys.js** 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5lka4wg3vcnqkhjr3puw.png)

In the file apiKeys.js I get all the apikeys from the .env file.

I will convert all those apikeys into an Array data.
Then I will export this array in order to get these apikeys in all the other JavaScript files.

You should also note that I get the first apikey in the .env file here at the end.

 ```javascript
   let API1 = process.env.REACT_APP_FOOD_API_KEY;
 ```

I will say later why this is.

---

**src / App.js**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ox0mej1g3vzhudvn0q9q.png)

I have first imported **ApiKeys** from "./api/ApiKeys" in the image above.

Then I have written a few spoonacular api links.

Then I get **apiKey** in the variable "getApiKey" using **useSelector** inside the App function.
    

```javascript
    import { useSelector,useDispatch } from "react-redux";

    // import api key Array
    import {ApiKeys} from './api/ApiKeys'
    // some api url
    const homeRecipeURL = 'https://api.spoonacular.com/recipes/random?number=21';
    const RecipeURL = 'https://api.spoonacular.com/recipes/';
    const SimilarRecipeURL = 'https://api.spoonacular.com/recipes/'

    const App = () =>{
    
    // get api key id 
    const getApiKey = 
     useSelector((state)=>state.apiKey_Data.apiKey)
  

    //some code...

    return(
     //some code...
    )
    }

    export default App;
```

---

Then inside the App function, we write an important and simple function.

This is going to hack / break that api limit 😎
That called as **changeAPiKey()**🔥
  

 ```javascript   
    import { UpdateApiKey } from "./store/action/updateApi";
    import { useSelector,useDispatch } from "react-redux";
    import { UpdateApiKey } from "./store/action/updateApi";

    const App = () =>{
   

    //some code...

    let apiCallTime = 0;
    const dispatch = useDispatch();

    const changeAPiKey = () => {// change api key when api limit hit 150 point, then it's throw 402 error
  
      let CurrentApi = ApiKeys[apiCallTime];
      dispatch(UpdateApiKey(CurrentApi));
  
      console.log("api limit error & status code = 4️⃣0️⃣2️⃣, but you don't worry, api was changed. so happy cooking 😁")
  
      apiCallTime++;
  
      if (apiCallTime > 8) {
        apiCallTime = 0;
      }
    };
  
    //some code...

    return(
     //some code...
    )
    }

    export default App;
```

Here I first wrote 

```javascript   
 let apiCallTime = 0;
```

Then I wrote 

 ```javascript
     const dispatch = useDispatch ();
 ```

You can tell by looking at the **changeAPiKey() function** above.

When changeAPiKey() first runs, it stores the api key in the "apiCallTime" position in the array **src / api / ApiKeys.js** as "CurrentApi".

 ```javascript
    let CurrentApi = ApiKeys[apiCallTime];
 ```

It then dispatches it to **UpdateApiKey** using **useDispatch()**.

Now the **Api Key Data** retrieved from the store will be updated by the "CurrentApi value".

So wherever we get **Api Key Data** in this entire react js app, it will be the updated new **API KEY ✨**.

---

**another continues function that call / run ChangeApiKey()**

```javascript
    // Home Page
    const [homeRecipeData,setHomeRecipeData] = React.useState([]);
    const [home,setHome] = React.useState(false);   
  
    useEffect( () => { 
        async function fetchData() {
            try {
                const apiResponse =  await axios.get(homeRecipeURL+`&apiKey=${getApiKey}`);
                const homeRecipeData = await apiResponse.data;
                setHomeRecipeData(homeRecipeData);
                setHome(true)
            } catch (err) {
                  if (err.response) {
                    if(err.response.status === 402 ){
                      changeAPiKey()
                    } 
                 }
                 console.log(err.response.data.message)
              }
        }
        fetchData();
    }, [getApiKey]);
```


Now in this **fetchData()** function I get 'api data' using 'api url' and 'api key' with the help of "axios".

In this I will use "initialApiKey" in the store as the 'api key' through "useSelector".

Probably 402 errors if "initialApiKey" runs out of 150 points per day.

If you get a 402 error like this, run the **ChangeApiKey()** function.

Then, as I said, the old 'api key' which gives 402 error will be replaced by the 'new api key' in the 'Array'.

---

I would have written the 'api key' at the beginning of the last .env in the array.
This is because the 'api key' used first in "initialApiKey" is the 'api key' at the beginning of the .env.

 If "initialApiKey" gives 402 error **ChangeApiKey()** will again use the 'api key' which returns the old error at the beginning of .env,

So I would have written the 'api key' at the beginning of the .env at the end of the array.

---

The website will continue to run as usual.

Celebrate a victory🎉💃💃💃 You have now exceeded the api limit...

I am use 10 free account api.

one free api =  150 point/day;

10 x 150 = 1500

So, you get freely 1500 point / pre day, even you don't pay for that. 

Now you save up to 29$ per month 🤑🤑🤑. 
You can save more on that if you think💸.


If you use the API KEY only once on your processor, you can do this using **redux** just **ChangeApiKey()**.

But I use **redux** because this application uses the updated "API KEY" in different javscript files in many places.


[DISCLAIMER: NO HARM INTENDED, THIS IS JUST TO CREATE A PUBLIC AWARENESS]