This is a log of my journey into web development and computer science.

Personal Portfolio

Important things:
Inheritance, this, closures, event loop

Package.json configs!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
{
"name": "",
"version": "1.0.0",
"description": "Reference implemenation of a Node.js & React shopping cart app.",
"main": "server/index.js",
"scripts": {
"dev": "npm-run-all --silent --parallel dev:*",
"dev:client": "webpack-dev-server",
"dev:server": "nodemon server/index.js",
"db:import": "source .env; psql $DATABASE_URL < database/dump.sql",
"db:export": "source .env; pg_dump -c -O $DATABASE_URL > database/dump.sql",
"build": "webpack --mode=production",
"start": "NODE_ENV=production node server/index.js"
},
"nodemonConfig": {
"watch": [
"server/"
],
"ignore": [
"server/public/",
"server/sessions/"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx}": [
"eslint --fix",
"git add"
]
},
"eslintIgnore": [
"server/public/main.js"
],
"eslintConfig": {
"env": {
"browser": true,
"node": true
},
"parser": "babel-eslint",
"extends": [
"plugin:react/recommended",
"eslint:recommended",
"standard"
],
"settings": {
"react": {
"version": "detect"
}
},
"rules": {
"semi": [
"error",
"always"
],
"padded-blocks": 0,
"arrow-parens": [
"error",
"as-needed"
],
"curly": [
"error",
"multi-line"
],
"no-console": [
"error",
{
"allow": [
"warn",
"error"
]
}
],
"space-before-function-paren": [
"error",
{
"anonymous": "always",
"named": "never",
"asyncArrow": "always"
}
],
"react/prop-types": 0
}
},
"dependencies": {
"dotenv": "8.2.0",
"express": "4.17.1",
"express-session": "1.17.0",
"pg": "7.17.1",
"react": "16.12.0",
"react-dom": "16.12.0",
"session-file-store": "1.3.1"
},
"devDependencies": {
"@babel/core": "7.8.0",
"@babel/plugin-transform-react-jsx": "7.8.0",
"babel-eslint": "10.0.3",
"babel-loader": "8.0.6",
"eslint": "6.8.0",
"eslint-config-standard": "14.1.0",
"eslint-plugin-import": "2.20.0",
"eslint-plugin-node": "11.0.0",
"eslint-plugin-promise": "4.2.1",
"eslint-plugin-react": "7.17.0",
"eslint-plugin-standard": "4.0.1",
"husky": "4.0.7",
"lint-staged": "9.5.0",
"nodemon": "2.0.2",
"npm-run-all": "4.1.5",
"webpack": "4.41.5",
"webpack-cli": "3.3.10",
"webpack-dev-server": "3.10.1"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
require('dotenv/config');
const path = require('path');

const clientPath = path.join(__dirname, 'client/');
const publicPath = path.join(__dirname, 'server/public/');

module.exports = {
resolve: {
extensions: ['.js', '.jsx']
},
entry: clientPath,
output: {
path: publicPath
},
module: {
rules: [
{
test: /\.jsx/,
use: {
loader: 'babel-loader',
options: {
plugins: [
'@babel/plugin-transform-react-jsx'
]
}
}
}
]
},
devtool: 'source-map',
devServer: {
contentBase: publicPath,
historyApiFallback: true,
host: '0.0.0.0',
port: process.env.DEV_SERVER_PORT,
proxy: {
'/api': `http://localhost:${process.env.PORT}`
},
stats: 'minimal',
watchContentBase: true
}
};

tl;dr: If a Component needs to alter one of its attributes at some point in time, that attribute should be part of its state, otherwise it should just be a prop for that Component.

props

props (short for properties) are a Component’s configuration, its options if you may. They are received from above and immutable as far as the Component receiving them is concerned.

A Component cannot change its props, but it is responsible for putting together the props of its child Components.

state

The state starts with a default value when a Component mounts and then suffers from mutations in time (mostly generated from user events). It’s a serializable* representation of one point in time—a snapshot.

A Component manages its own state internally, but—besides setting an initial state—has no business fiddling with the state of its children. You could say the state is private.

* We didn’t say props are also serializable because it’s pretty common to pass down callback functions through props.

Changing props and state

props state
Can get initial value from parent Component? Yes Yes
Can be changed by parent Component? Yes No
Can set default values inside Component?* Yes Yes
Can change inside Component? No Yes
Can set initial value for child Components? Yes Yes
Can change in child Components? Yes No

* Note that both props and state initial values received from parents override default values defined inside a Component.

Should this Component have state?

state is optional. Since state increases complexity and reduces predictability, a Component without state is preferable. Even though you clearly can’t do without state in an interactive app, you should avoid having too many Stateful Components.

Component types

  • Stateless Component — Only props, no state. There’s not much going on besides the render() function and all their logic revolves around the props they receive. This makes them very easy to follow (and test for that matter). We sometimes call these dumb-as-f*ck Components (which turns out to be the only way to misuse the F-word in the English language).
  • Stateful Component — Both props and state. We also call these state managers. They are in charge of client-server communication (XHR, web sockets, etc.), processing data and responding to user events. These sort of logistics should be encapsulated in a moderate number of Stateful Components, while all visualization and formatting logic should move downstream into as many Stateless Components as possible.

Copied from props vs state