|
@@ -9,6 +9,8 @@
|
|
|
* React dev tools
|
|
|
|
|
|
## Video 2: Thinking and Understanding React Components
|
|
|
+* https://facebook.github.io/react/docs/react-component.html
|
|
|
+
|
|
|
* React applications are split into components which share information over different ways like state and properties.
|
|
|
|
|
|
## Video 3: Our First React Component
|
|
@@ -79,9 +81,9 @@ class MyComponent extends React.Component {
|
|
|
```javascript
|
|
|
const MyFunction = (props) => {
|
|
|
return(
|
|
|
- <p>{props.myProp}</p>
|
|
|
- <p>{props.myObj}</p>
|
|
|
- <p>{props.onClick}</p>
|
|
|
+ <p>{props.myProp}<\/p>
|
|
|
+ <p>{props.myObj}<\/p>
|
|
|
+ <p>{props.onClick}<\/p>
|
|
|
)
|
|
|
}
|
|
|
```
|
|
@@ -95,15 +97,16 @@ import { BrowserRouter, Match, Miss } from 'react-router'
|
|
|
const Root = () => {
|
|
|
return (
|
|
|
<BrowserRouter>
|
|
|
- <Match exactly pattern='/' component={MyComponent}/>
|
|
|
- <Match pattern='/mystuff/:myarg' component={MyStuff} />
|
|
|
- <Miss component={OhNo} />
|
|
|
- </BrowserRouter>
|
|
|
+ <Match exactly pattern='/' component={MyComponent} \/>
|
|
|
+ <Match pattern='/mystuff/:myarg' component={MyStuff} \/>
|
|
|
+ <Miss component={OhNo} \/>
|
|
|
+ <\/BrowserRouter>
|
|
|
)
|
|
|
}
|
|
|
|
|
|
render(<Root />, document.getElementById('main'))
|
|
|
```
|
|
|
+* (Video 18): the ':myarg' will be available as ```this.props.params.myarg```
|
|
|
|
|
|
## Video 10: Helper and Utility Functions
|
|
|
* Organize helper functions in separate files.
|
|
@@ -131,10 +134,10 @@ class MyClass extends React.Component {
|
|
|
}
|
|
|
render () {
|
|
|
return (
|
|
|
- <p onClick={this.myFunction.bind(this)}>test</p>
|
|
|
- <p onClick={(e) => {this.myFunction(e)}}>test</p>
|
|
|
+ <p onClick={this.myFunction.bind(this)}>test<\/p>
|
|
|
+ <p onClick={(e) => {this.myFunction(e)}}>test<\/p>
|
|
|
or
|
|
|
- <p onClick={this.myFunction}>test</p> Needs constructor hack
|
|
|
+ <p onClick={this.myFunction}>test<\/p> Needs constructor hack
|
|
|
)
|
|
|
}
|
|
|
}
|
|
@@ -160,3 +163,162 @@ this.context.router.transitionTo('...')
|
|
|
```
|
|
|
|
|
|
## Video 13: Understanding State
|
|
|
+* Whenever you want to change anything on your page, you change the state data instead.
|
|
|
+* Put the state on the main parent component
|
|
|
+* Initialize with
|
|
|
+```javascript
|
|
|
+class App extends React.Component {
|
|
|
+ constructor () {
|
|
|
+ super()
|
|
|
+ this.state = {
|
|
|
+ child1state = {},
|
|
|
+ child2state = {},
|
|
|
+ }
|
|
|
+ }
|
|
|
+ render (
|
|
|
+ return (
|
|
|
+ ...
|
|
|
+ )
|
|
|
+ )
|
|
|
+}
|
|
|
+```
|
|
|
+* When changing the state, you must avoid race conditions. Follow this scheme:
|
|
|
+ - make a copy of the state
|
|
|
+ - update the copy
|
|
|
+ - set the state with copy
|
|
|
+```javascript
|
|
|
+class App extends React.Component {
|
|
|
+ constructor () {
|
|
|
+ super()
|
|
|
+ this.addChild1StateElement = this.addChild1StateElement.bind(this)
|
|
|
+ }
|
|
|
+ addChild1StateElement (elem) {
|
|
|
+ const child1state = { ...this.state.child1state }
|
|
|
+ child1state['new-item'] = elem
|
|
|
+ this.setState({ child1state })
|
|
|
+ }
|
|
|
+ render (
|
|
|
+ <ChildComponent addElem={this.addChild1StateElement} \/>
|
|
|
+ )
|
|
|
+}
|
|
|
+```
|
|
|
+* Create state manipulating functions on the main component and pass it to the children through props.
|
|
|
+
|
|
|
+## Video 14: Loading Data Into State On Click
|
|
|
+* Can be used to load an initial object to the state.
|
|
|
+
|
|
|
+## Video 15: Displaying State with JSX
|
|
|
+* Dynamically generate HTML tags based on state data
|
|
|
+* React recognizes state changes and re-renders the data
|
|
|
+* Example for
|
|
|
+```javascript
|
|
|
+...
|
|
|
+ render () {
|
|
|
+ return (
|
|
|
+ <ul>
|
|
|
+ {Object.keys(this.state.child1state).map(key =>
|
|
|
+ <ChildComponent key={key} details={this.state.child1state[key]}\/>
|
|
|
+ )}
|
|
|
+ <\/ul>
|
|
|
+ )
|
|
|
+ }
|
|
|
+...
|
|
|
+```
|
|
|
+* each element in a loop needs a 'key' attribute, so React can keep track!
|
|
|
+* if you pass down 'key' itself, use a different name, e.g. index!
|
|
|
+* use data massaging to extract variables for easier access
|
|
|
+```javascript
|
|
|
+const { details } = this.props
|
|
|
+```
|
|
|
+
|
|
|
+## Video 16: Updating Order State
|
|
|
+* emphasizing **if you pass down 'key' itself, use a different name, e.g. index!**
|
|
|
+
|
|
|
+## Video 17: Displaying Order State
|
|
|
+* Use ```Object.keys(...).reduce((prevValue, key)=>{...}, initValue)``` to make a scalar of an object.
|
|
|
+* Don't forget to check is elements are valid (can change in real-time).
|
|
|
+
|
|
|
+## Video 18: Persisting State with Firebase
|
|
|
+* Uses 're-base' to sync state with firebase web app
|
|
|
+* https://facebook.github.io/react/docs/state-and-lifecycle.html
|
|
|
+* use componentWillMount() to sync the state before the component loads.
|
|
|
+* this way, the component will render only once.
|
|
|
+* How to use react-router parameters
|
|
|
+* use componentWillUnmount() to stop syncing with the database.
|
|
|
+
|
|
|
+## Video 19: Persisting Order with localstorage
|
|
|
+* Uses cookies to store data locally
|
|
|
+* use componentWillUpdate(nextProps, nextState) in this case, because it is called every time state or props is updated.
|
|
|
+```javascript
|
|
|
+...
|
|
|
+ componentWillMount () {
|
|
|
+ const localStorageRef = localStorage.getItem('mykey')
|
|
|
+ if (localStorage) {
|
|
|
+ this.setState({ order: JSON.parse(localStorageRef) })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ componentWillUpdate () {
|
|
|
+ localStorage.setItem('mykey', JSON.stringify(nextState.mykey))
|
|
|
+ }
|
|
|
+...
|
|
|
+```
|
|
|
+* use shouldComponentUpdate() to check data before it is rendered. Returns true if component should be re-rendered or false if not.
|
|
|
+
|
|
|
+## Video 20: Bi-directional Data Flow and Live State Editing
|
|
|
+* When you write forms,
|
|
|
+* You can used computed properties
|
|
|
+```javascript
|
|
|
+...
|
|
|
+ handleChange (event, key) {
|
|
|
+ const prev = this.props.prevs[key]
|
|
|
+ const next = { ...prev, [event.target.name]: event.target.value }
|
|
|
+ this.setState(next)
|
|
|
+ }
|
|
|
+ render () {
|
|
|
+ return (
|
|
|
+ <input type='text' name='name' value={thing.name} placeholder='Thing name' onChange={(event) => this.handleChange(event, key)} \/>
|
|
|
+ )
|
|
|
+ }
|
|
|
+...
|
|
|
+```
|
|
|
+
|
|
|
+## Video 21: Removing Items From State
|
|
|
+* CRUD - Create Read Update Delete
|
|
|
+* ```child1state[key] = null``` is required by Firebase. Otherwise, ```delete child1state[key]``` is also possible
|
|
|
+```javascript
|
|
|
+...
|
|
|
+ deleteElement (key) {
|
|
|
+ const child1state = { ...this.statte.child1state }
|
|
|
+ child1state[key] = null
|
|
|
+ this.setState({ child1state })
|
|
|
+ }
|
|
|
+...
|
|
|
+```
|
|
|
+* You can store JSX in a variable.
|
|
|
+
|
|
|
+## Video 22: Animating React Components
|
|
|
+* use npm package concurrently to concurrently start npm scripts
|
|
|
+* use CSSTransitionGroup from 'react-addons-css-transition-group'
|
|
|
+* adds and removes again classes to animated items
|
|
|
+* class items can be styled with CSS
|
|
|
+* replace parent element of animation
|
|
|
+ - e.g. <ul className='myclass'> becomes <CSSTransitionGroup className='myclass' component='ul' transitionName⁼'mytrans', transitionEnterTimeout={100} transitionLeaveTimeout={200}>
|
|
|
+```stylus
|
|
|
+.mytrans
|
|
|
+ background blue
|
|
|
+ max-height 0px
|
|
|
+ transition all 0.5s
|
|
|
+ transform translateX(-120%)
|
|
|
+ ...
|
|
|
+ &.order-enter-active
|
|
|
+ background yellow
|
|
|
+ max-height auto
|
|
|
+ transform translateX(0)
|
|
|
+```
|
|
|
+* The time in transitionEnterTimeout should match the transition all <>s
|
|
|
+* There are three actions:
|
|
|
+ - enter
|
|
|
+ - leave
|
|
|
+ - appear
|
|
|
+
|
|
|
+## Video 23: Authentication
|