- webpack: used awesome-typescript-loader and html-webpack-plugin
- circle ci
- test coverage
- auto test, auto bundle, and auto npm publish after push!
- react router
- used scss attribute selector to avoid interference
- used react protal to prevent context stacking
- have highlited code demo
Dialog: onClose={() => { ReactDOM.render( React.cloneElement(component, { visible: false }), div ); ReactDOM.unmountComponentAtNode(div); div.remove(); }} re-render the component to change the attribute: visible. Cloned the component and then overwrite the property. there was an extra div to remove: remove the events attached onto the div first with "ReactDOM.unmountComponentAtNode()". And then remove the div.
form validation Asychornous validation with promise.all***** very complicated - challenge Promise.all only accepts arrays. So I used nested arrays first. And then combine the nested arrays together into one long nested array. And then zip the array
Used yarn (try to avoid npm), webpack 4, webpack-dev-server 3, TypeScript 3
- Make directories and create library - used git repo
- npm init -y - creates package.json
- Create lib/index.tsx after installed webpack - yarn add webpack webpack webpack-cli -dev
- Create webpack.config.js: - setup entry, output, modeule.rules(jsx, tsx, scss), plugins - translates entry scripts with rules defined, and different loaders. - output to the absolute address defined. Use path.resolve to parse addresses for different operating systems. - ouput libraryTarget: use umd to accomodate for both commonJS and amd. - pack index.tsx into index.js
- Setup webpack-dev-server, and webpack.config.dev.js - webpack-dev-server monitors the 8080 port - webpack-dev-server also provides realtime translation of the tsx document into js strings in memories for faster speed - when the user visits the 8080/js document, the server takes the js strings in memory and presents it to the user - now we can use "npx webpack-dev-server" command to launch a server for development. or "yarn start" as defined in package.json
- Create index.html
- Setup webpack.config.prod.js
- Create examples preview and webpack config.doc.js
- Introduce tests
- Introduce CI (continuous integration, used circle CI)
- Setup tsconfig.json and tslint.json
- Setup scripts (yarn start, yarn build, yarn test)
- Customized tasks (yarn task create component x)
- What do dev, prod, and test envrironments do?
- Why seperating these environments?
- Why do we generate index.html instead of mannually write one?
- The index.html scripts depends on the config setups in other scripts. Genertating the index.html automates the work flow and avoids possible human mistakes.
- What does CI do?
- How to start developing?
A webpack plugin to automatically generate and update html file that includes all the webpack bundle and config updates.
```linux
--save-dev
--dev
-S-D
```
For pachages that are only used by developers. Example: Webpack, TypeScript
```linux
--save
-S
```
For packages that are also used by users (users' browser). Example: React, jQuery
--save is the default setting if nothing is added for installation.
- The lock file for yarn. (gnerated when using yarn to manage npm dependencies.)
- It locks down the versions for all the dependencies specified in the package.json file. Ther versions do not have to be the same as long as it works.
Exclude React and react DOM from the packed bundle becasue the users of this react UI library definetrly have react installed already. Excluding by setting "externals" module in the webpack.config file:
externals: {
react: {
commonjs: "react",
commonjs2: "react",
amd: "react",
root: "React",
},
"react-dom": {
commonjs: "react-dom",
commonjs2: "react-dom",
amd: "react-dom",
root: "ReactDOM",
}
Importing ADDRESS: Use relative address if importing from your own file Use library name if importing from third-party library.
importing default export: import GIVEN_NAME from ADDRESS
importing named values: import {PARA_NAME} from ADDRESS
importing a combination: import GIVEN_NAME, {PARA_NAME, ...} from ADDRESS
define a function with format: x = () => {}
constructor(props){ super(props); this.state = { n: 1 }; } ... x = () => { this.setState({ n: 2 }) }
It is a simplified way of definining this.x in the consturctor. Therefore, this method has a problem of taking too much memory. Every case ran requies it's own definition of this.x.
Mannually bind this in jsx
button
Mannually bind this in the consturctor.
constructor(props){ super(props); this.state = { n: 1 }; this.y = this.x.bind(this) } ... button
Method 1 is the simplified version of method 3.
The empty second variable of useEffect hook makes it runs only once when mounted. Perfect chance to use axios.get information here.
useEffect(() => { axios.get('') }, [])
static: suitable for tree-shaking optimization but not as convinent for importing many items dynamic: scalable
sass loader translates scss doc into css doc as strings. css laoder converts the css doc into an object with strings inside. style loader converts the object into a style tag enclosing the css. general process as follows:
style_tag = document.createElement("style tag") style_tag.innerHTML = "css" document.head.appendChild(style_tag)
major.minor.patch
commands: (comes with auto git commit) npm version major >>>> 0.0.1 -> 1.0.0 for major change in API, affects cuurent code npm version minor >>>> 0.0.1 -> 0.1.0 for minor change in API, doesn't affect current code npm version patch >>>> 0.0.1 -> 0.0.2 for bug fixes, no API changes
ReactElement can only take tags. ReactNode can take both tags and strings.
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
- Use example for easier development
- Used Scoped CLass (higher-order function) for quicker tag naming. Used "syhui-" prefix to avoid interference.
- Used React Fragment to attach multiple divs without creating extra layer
- Render element based on visbility: const output = props.visible && (). or use props.visible? (render): null. If else is too much trouble.
- Used React Portal to move the node away from it's original parent. Move the content to document.body to avoid context stacking or event bubbling.
- Dynamically render/generate components: declare component as const. Attach the component inside a div, and then append the div onto document.body.
- Pass API from enclosure: return a function that controls the varibale inside the enclosure
-
Receive attributes for layout may overwirte pre-written classes. Deconstruct props first: const { className, ...rest } = props; And then join the pre-written class name with given classname to be the final className. Use "...rest" for the rest of the props attributes. <div className={[sc(), className].join(" ")} {...rest}>
But this method is so inconnvienet... Then I improved scopeMaker function to takein the extra classname
-
Used Functional Programming to refactor scopedClassMaker!!!
-
Used NavLink for the "active" state displayment
- General and widely applicable(ie. AntD), but is more complicated in use
- Focused and customed(libraries used inside companies): less overall support but more user friendly and customized
Reccomend forms to use controlled components: useState as only source of truth. Principle of React UI component: UI = f(state)
How to get the value of the controlled and uncontrolled input field?
controlled: const [name, setName] = useState("syh") <input value={name} onChange={(e) => setName(e.target.value)}/ >
uncontrolled:
const refInput = useRef(null); const x = () => { conosle.log( refInput.current!.value); }
feedback all the value on change:
- No need to reprocess the data.
- Might be slow if there are tons of input, but it's a rare case