Fullstacking: Restructuring the project
Tags: reactnative, javascript, npm
Published: 2019-09-03 12:30:30

Ok, so I've gone to [@fotontech](https://dev.to/fotoncompany) to get some help to set up Relay and over so many new concepts, new files and new tools I had to refactor our project's structure.
So we're basically restarting with everything we've learned so far
, and we'll be using the project's structure similar to [Entria Fullstack](https://github.com/entria/entria-fullstack). 
Our project will have a main package and other sub-packages like our react-native app and server.


## Restarting

Within another folder, run the following commands:
```javascript
npm init // creates new package
git init // initiate git local repository
git add . // stage all folders and files to be commited
git commit -m "main package created" // commits staged files
git remote add origin <url> // links it with remote repository
git push -u origin master // pushes commits setting upstream from master to origin
// you may use -f flag to force push to the older remote repository 
```

## React Native

```javascript
mkdir packages // creates folder packages
cd packages // move to packages folder
react-native init app // creates a new react-native project
// you can also 'expo init app' to set up a react-native project with expo
cd app
yarn start // starts app
// On another terminal, but the same folder:
react-native run-android // builds the app into your connected smartphone
```
You might want to check [this guide](https://dev.to/heymarkkop/fullstacking-setting-up-react-native-1g21) to set up android stuff

You might also configure the following scripts:
```javascript
// package.json
  "scripts": {
    "start:app": "yarn --cwd packages/app start",
    "android": "yarn --cwd packages/app/android android",
    "shake": "adb shell input keyevent 82", // shakes phone
    "test": "jest"
  }
```

```javascript
// packages/app/package.json
  "scripts": {
    "start": "react-native start",
    "android": "react-native run-android",
    "test": "jest",
    "lint": "eslint ."
  }
```

## NodeJS + KoaJS

```javascript
mkdir server // in packages folder
cd server
npm init // creates a new package
yarn add koa mongoose // adds koa and mongoose dependencies
sudo service mongod start // starts mongodb service
```

```javascript
// packages/server.js
const Koa = require("koa");
const mongoose = require("mongoose");

const databaseUrl = "mongodb://127.0.0.1:27017/test";
mongoose.connect(databaseUrl, { useNewUrlParser: true });
mongoose.connection.once("open", () => {
  console.log(`Connected to database: ${databaseUrl}`);
});

const app = new Koa();
app.use(async ctx => {
  ctx.body = "Hello World";
});
app.listen(3000, () =>
  console.log("Server is running on http://localhost:3000/")
);
```

Run `node server.js` to test it
Don't forget to `sudo service mongod start`.
We shall add `"start": "nodemon server.js"` in the `scripts` object in this `package.json`
And `"start:server": "yarn --cwd packages/server start"` in our root `packages.json` like we just did with `start:app`

## Mongoose

Now we're going to connect everything and display our database's object (a stapler) in the frontend.

Create the model file again
```javascript
// packages/server/models/Product.js
var mongoose = require('mongoose');

const ProductSchema = new mongoose.Schema({
  title: String,
});

module.exports = mongoose.model('Product', ProductSchema);
```

Add query to the `server.js` file
```javascript
// packages/server/server.js
const Koa = require("koa");
const mongoose = require("mongoose");
const Product = require("./models/Product");

const databaseUrl = "mongodb://127.0.0.1:27017/test";
mongoose.connect(databaseUrl, { useNewUrlParser: true });
mongoose.connection.once("open", () => {
  console.log(`Connected to database: ${databaseUrl}`);
});

const app = new Koa();

const query = () => {
  return new Promise((resolve, reject) => {
    Product.find({}, (err, res) => {
      if (err) {
        reject(err);
      }
      resolve(res);
    });
  });
};

app.use(async ctx => {
  const data = await query();
  ctx.body = data;
});
app.listen(3000, () =>
  console.log("Server is running on http://localhost:3000/")
);
```

And finally `yarn add axios` and add a GET hook in `App.js` file
```react
// packages/app/App.js
import React, {Fragment, useState, useEffect} from 'react';
import axios from 'axios';
import {Text} from 'react-native';

const App = () => {
  const [title, setTitle] = useState('Loading...');
  useEffect(() => {
    const fetchData = async () => {
      const result = await axios('http://localhost:3000');
      setTitle(result.data[0].title);
    };
    fetchData();
  }, []);

  return (
    <Fragment>
      <Text>Hello World! Product: {title} </Text>
    </Fragment>
  );
};

export default App;
```
Now with `yarn start:server` and `yarn start:app` we should be able to see our stapler title "Stampler" on our smartphone's screen.
And I've just realized that I've misspelled stapler this entire time.

Our repository should be looking like this version:
[Fullstacking - GitHub - #9724f4cb35](https://github.com/Markkop/fullstacking/tree/9724f4cb3526f53efedd3188bf0a3efd348ae682)

We're now ready to start adding Relay and GraphQL into our app.
Since we were growing in complexity, it was important to organize our project to optimize our time.

References:
[Koa, express, node simplified version connected to MongoDB](https://developpaper.com/koa-express-node-simplified-version-connected-to-mongodb/)
[How to fetch data with React Hooks?](https://www.robinwieruch.de/react-hooks-fetch-data)
[Entria - Monorepo Playground with GraphQL, React, React Native, Relay Modern, TypeScript and Jest ](https://github.com/entria/entria-fullstack)