David Wu
-
contact
- twitter: @wulymammoth
- github: github.com/wulymammoth
-
work
- currently: senior software engineer on infrastructure, EasyPost
- previously: full-stack engineer, The RealReal
-
background
- primarily self-taught
- undergraduate studies at the University of California, Berkeley
- ISF (interdisciplinary studies field)
- computer science
- cognitive science
- statistics
- sociology
- psychology
- ISF (interdisciplinary studies field)
Learn about how most web-applications and services that we use from AirBnb, to Instagram, to how your packages get to your doorstep are built today
You may have heard a lot about ReactJS or even have dabbled in it. You also may have heard about NodeJS or have even dabbled in it. I want to give you a good mental model on how all the pieces fit together and play together to hopefully give you all a starting point or foundation in which to start exploring more should this be of immense interest to you.
I'll start by discussing what things look like in a web service or application from a high level and some of the pieces involved, including some of the nomenclature common in this domain, and then we'll dive into some code. I'll be focusing more on the "backend" or API/server-side with NodeJS today, and if we have time, we'll talk about how to get what we have up onto the web and/or build on it.
Please, feel free to stop me at any time to ask questions.
- understanding client vs server
- why we need servers
- requests and responses
- a terminal application
- NodeJS installed
- Git installed
- a text-editor like Visual Studio Code - https://code.visualstudio.com/
-
install Express w/ Express application generator | https://expressjs.com/en/starter/generator.html
DEBUG=api:* PORT=3001 npm start
-
install Create React App (CRA) | https://create-react-app.dev/docs/getting-started
npx create-react-app my-app cd my-app npm start
var React = require("react");
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
decrement() {
this.setState({ count: this.state.count - 1 });
}
increment() {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<span onClick={() => this.decrement()}>-</span>
<span>{this.state.count}</span>
<span onClick={() => this.increment()}>+</span>
</div>
);
}
}
import "./App.css";
var React = require("react");
async function postData(url = "", data = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
return response.json(); // parses JSON response into native JavaScript objects
}
class ListItem extends React.Component {
constructor(props) {
super(props);
this.state = { idx: props.key, name: props.name, purchased: false };
}
toggleCheck() {
const newState = Object.assign(this.state, { purchased: !this.state.purchased });
this.setState(newState);
postData("/items", { foo: "bar" }).then((data) => {
console.log(data);
});
}
render() {
return (
<li>
<input type="checkbox" defaultChecked={this.state.purchased} onChange={() => this.toggleCheck()} />
<label>{this.state.name}</label>
</li>
);
}
}
class ShoppingList extends React.Component {
constructor(props) {
super(props);
this.state = { items: [] };
}
componentDidMount() {
fetch("/items")
.then((response) => response.json())
.then((data) => {
this.setState({ items: data.items });
});
}
render() {
const items = this.state.items;
return (
<ul>
{items.map((item, idx) => (
<ListItem key={idx} name={item} />
))}
</ul>
);
}
}
class EntryField extends React.Component {
constructor(props) {
super(props);
this.state = { entry: "" };
}
handleInput = (event) => {
this.setState({ entry: event.target.value }, () => {
console.log(`'entry' state: ${this.state.entry}`);
});
};
handleSubmit = (event) => {
postData("/items", { item: this.state.entry }).then((data) => {
console.log(data);
});
};
render() {
return (
<div>
<input onChange={this.handleInput} type="text" id="entry" name="entry" placeholder="add new entry" />
<button onClick={this.handleSubmit}>submit</button>
</div>
);
}
}
function App() {
return (
<div className="App">
<Counter />
<br />
<ShoppingList />
<br />
<EntryField />
</div>
);
}
export default App;
// EXPRESS (API)
var express = require("express");
var router = express.Router();
let counter = 0;
let items = [];
/* GET home page. */
router.get("/", function (req, res, next) {
res.render("index", { title: "foobar" });
});
router.get("/foobar", function (_req, res, _next) {
res.send("foobar baz\n");
});
router.get("/items", function (_req, res, _next) {
res.send({ items: items });
});
router.post("/items", function (req, res, _next) {
const newItem = req.body.item;
items.push(newItem);
console.log(++counter);
res.send({ items: items });
//res.status(200).end();
});
module.exports = router;
- using the browser's "fetch" API
GET
: for fetching dataPOST
: for creating and persisting data