timqian / my-notes

https://github.com/timqian/my-notes/issues
7 stars 2 forks source link

React and mobx and redux #116

Open timqian opened 7 years ago

timqian commented 7 years ago

React basic concepts

const name = 'timqian';

// embed js expression in curly braces
const element = <h1> Hi {name} </h1>;

// Specify attributes
// react dom escapes value embedded in curly braces; prevent XSS
const element1 = <div tabIndex="0"></div>;
const element2 = <img src={user.avatarUrl}></img>;

// Specifying Children ( Note: React DOM uses camelCase property naming convention instead of HTML attribute names.)
const element3 = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);

// JSX will be compiles to React.createElement() calls

// Render JSX:
ReactDOM.render(
  element,
  document.getElementById('root')
);

// Update renderd Element
// Call ReactDOM.render() again with new element
// React DOM compares the element and its children to the previous one, 
// and only applies the DOM updates necessary to bring the DOM to the desired state.
function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(
    element,
    document.getElementById('root')
  );
}

setInterval(tick, 1000);

// Component
// When React sees an element representing a user-defined component,
// it passes JSX attributes to this component as a single object(props),
// run it and return the result.
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

// Extract components from big components make the app easy to change and resue components
// https://facebook.github.io/react/docs/components-and-props.html#extracting-components
// Don't change props value; make component "pure"

// hande events
<button onClick={activateLasers}>
  Activate Lasers
</button>
timqian commented 7 years ago

MOBX manage states of react app

state ==[auto update]==> view ^ [update]

action

image

Concepts

Simple example

// https://jsbin.com/fumerup/edit?js,output

import { observer } from 'mobx-react'
import { observable, action } from 'mobx'

class TickerStore {
  @observable time = 0

  @action incr = () => {
    this.time += 1
  }

  @action desc = () => {
    this.time -= 1
  }
}

const Ticker = observer(({ tickerStore }) => (
  <div>
    <span>tick {tickerStore.time} times</span>
    <button onClick={tickerStore.incr}>+</button>
    <button onClick={tickerStore.desc}>-</button>
  </div>
))

const tickerStore = new TickerStore()

ReactDOM.render(<Ticker tickerStore={tickerStore} />, document.querySelector('#app'))
timqian commented 6 years ago

Redux

The whole state of your app is stored in an object tree inside a single store. The only way to change the state tree is to emit an action, an object describing what happened. To specify how the actions transform the state tree, you write pure reducers.

Simple example

// https://github.com/jackielii/simplest-redux-example/blob/master/index.js
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import { Provider, connect } from 'react-redux'

// React component
class Counter extends Component {
  render() {
    const { value, onIncreaseClick } = this.props
    return (
      <div>
        <span>{value}</span>
        <button onClick={onIncreaseClick}>Increase</button>
      </div>
    )
  }
}

Counter.propTypes = {
  value: PropTypes.number.isRequired,
  onIncreaseClick: PropTypes.func.isRequired
}

// Action
const increaseAction = { type: 'increase' }

// Reducer
function counter(state = { count: 0 }, action) {
  const count = state.count
  switch (action.type) {
    case 'increase':
      return { count: count + 1 }
    default:
      return state
  }
}

// Store
const store = createStore(counter)

// Map Redux state to component props
function mapStateToProps(state) {
  return {
    value: state.count
  }
}

// Map Redux actions to component props
function mapDispatchToProps(dispatch) {
  return {
    onIncreaseClick: () => dispatch(increaseAction)
  }
}

// Connected Component
const App = connect(
  mapStateToProps,
  mapDispatchToProps
)(Counter)

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)