uniquejava / blog

My notes regarding the vibrating frontend :boom and the plain old java :rofl.
Creative Commons Zero v1.0 Universal
11 stars 5 forks source link

ES6 JSX tricks #148

Open uniquejava opened 7 years ago

uniquejava commented 7 years ago

class static properties

class Summary extends React.Component {

  static propTypes = {
    ingredients: PropTypes.number,
    steps: PropTypes.number,
    title: (props, propName) => 
      (typeof props[propName] !== 'string') ?
          new Error("A title must be a string") : 
          (props[propName].length > 20) ?
              new Error(`title is over 20 characters`) :
              null
  }

  static defaultProps = {
    ingredients: 0,
    steps: 0,
    title: "[recipe]"
  }
  render() {
     const {ingredients, steps, title} = this.props
     ...
  }

Refs

写法一

import { Component } from 'react'

class AddColorForm extends Component {
  constructor(props) {
    super(props)
    this.submit = this.submit.bind(this)
  }
  submit(e) {
    const { _title, _color } = this.refs
    e.preventDefault();
    alert(`New Color: ${_title.value} ${_color.value}`)
    _title.value = '';
    _color.value = '#000000';
    _title.focus();
  }
  render() {
      return (
          <form onSubmit={this.submit}>
              <input ref="_title”“ type="text" 
                     placeholder="color title..." required/>
              <input ref="_color"
                     type="color" required/>
              <button>ADD</button>
          </form>
      )
  }
}

写法二: Stateless Functional Components (SFC)

“const AddColorForm = ({onNewColor=f=>f}) => {
    let _title, _color
    const submit = e => {
        e.preventDefault()
        onNewColor(_title.value, _color.value)
        _title.value = ''
        _color.value = '#000000'
        _title.focus()
    }
    return (
        <form onSubmit={submit}>
            <input ref={input => _title = input}
                   type="text" 
                   placeholder="color title..." required/>
            <input ref={input => _color = input}
                   type="color" required/>
            <button>ADD</button>
        </form>
    )
}

写法三

<input ref={input => this.text = input}/>

用map代替for循环

[...Array(totalStars)].map((n, i) =>
  <Star key={i}  selected={i<starsSelected} onClick={() => this.change(i+1)} />

完整实例:

class StarRating extends Component {

    constructor(props) {
        super(props)
        this.state = {
            starsSelected: props.starsSelected || 0
        }
        this.change = this.change.bind(this)
    }

    change(starsSelected) {
        this.setState({starsSelected})
    }

    render() {
        const {totalStars} = this.props
        const {starsSelected} = this.state
        return (
            <div className="star-rating">
                {[...Array(totalStars)].map((n, i) => 
                    <Star key={i}
                          selected={i<starsSelected}
                          onClick={() => this.change(i+1)}
                    />
                )}
                <p>{starsSelected} of {totalStars} stars</p>
            </div>
        )
    }

}

StarRating.propTypes = {
    totalStars: PropTypes.number
}

StarRating.defaultProps = {
    totalStars: 5
}

render(
    <StarRating totalStars={7} starsSelected={3} />,
    document.getElementById('react-container')
)

super(props)的作用: Invoking super initializes the component instance, and React.Component decorates that instance with functionality that includes state management. After invoking super , we can initialize our component’s state variables.

Passing Data Back Up the Component Tree

import { Component } from 'react'
import { v4 } from 'uuid'
import AddColorForm from './AddColorForm'
import ColorList from './ColorList'

export class App extends Component {

    constructor(props) {
        super(props)
        this.state = {
            colors: []
        }
        this.addColor = this.addColor.bind(this)
    }

    addColor(title, color) {
        const colors = [
            ...this.state.colors,
            {
                id: v4(),
                title,
                color,
                rating: 0
            }
        ]
        this.setState({colors})
    }

    render() {
        const { addColor } = this
        const { colors } = this.state
        return (
            <div className="app">
                <AddColorForm onNewColor={addColor} />
                <ColorList colors={colors} />
            </div>
        )
    }

}

bind的作用: This function(addColor) is bound to the component in the constructor, which means that it has access to this.state and this.setState

render method is invoked after every setState call

uniquejava commented 7 years ago

Mounting Lifecycle

screenshot 2017-11-15_22-49-07

ES6 class React.createClass()
getDefaultProps()
constructor(props) getInitialState()
componentWillMount() componentWillMount()
render() render()
componentDidMount() componentDidMount()
componentWillUnmount() componentWillUnmount()

stateless functional component

简单版

const StarRating = ({starsSelected=0, totalStars=5, onRate=f=>f}) =>
    <div className="star-rating">
        {[...Array(totalStars)].map((n, i) =>
            <Star key={i} selected={i<starsSelected} onClick={() => onRate(i+1)}/>
        )}
        <p>{starsSelected} of {totalStars} stars</p>
    </div>

const ColorList = ({ colors=[] }) =>
    <div className="color-list">
        {(colors.length === 0) ?
            <p>No Colors Listed. (Add a Color)</p> :
            colors.map(color =>
                <Color key={color.id} {...color} />
            )
        }
    </div>

const Color = ({title,color,rating=0,onRemove=f=>f,onRate=f=>f}) =>
    <section className="color">
        <h1>{title}</h1>
        <button onClick={onRemove}>X</button>
        <div className="color"
             style={{ backgroundColor: color }}>
        </div>
        <div>
            <StarRating starsSelected={rating} onRate={onRate} />
        </div>
    </section>

带callback的版本.

...

uniquejava commented 7 years ago

componentDidMount + fetch示例

npm install isomorphic-fetch --save

import { Component } from 'react'
import { render } from 'react-dom'
import fetch from 'isomorphic-fetch'

class CountryList extends Component {

    constructor(props) {
        super(props)
        this.state = {
            countryNames: [],
            loading: false
        }
    }

    componentDidMount() {
        this.setState({loading: true})
        fetch('https://restcountries.eu/rest/v1/all')
            .then(response => response.json())
            .then(json => json.map(country => country.name))
            .then(countryNames => 
                this.setState({countryNames, loading: false})
            )
    }

    render() {
        const { countryNames, loading } = this.state
        return (loading) ?
            <div>Loading Country Names...</div> :
            (!countryNames.length) ?
                <div>No country Names</div> :
                <ul>
                    {countryNames.map(
                        (x,i) => <li key={i}>{x}</li>
                    )}
                </ul>
    }

}