react - Offirmo-team/wiki GitHub Wiki

Voir aussi flux, Jest, enzyme, redux, reactive programming, appli web, javascript, AngularJS...

Introduction

officiel

Quick ref:

Tutoriels

courses

Advocacy

sécurité

Voir aussi appli web#Sécurité

Installation

Brut

concepts

good practices

Utilisation

+++ petits exemples http://ricostacruz.com/cheatsheets/react.html

Bonnes pratiques

+++ https://github.com/planningcenter/react-patterns

API de base

Composant "stateles" : https://medium.com/@joshblack/stateless-components-in-react-0-14-f9798f8b992d#.g1n3ka57q

import React, { Component, Fragment } from 'react'
import PropTypes from 'prop-types'

const SomeViewM = React.memo(
   function SomeView({children, title, onClick}) {
      return (
         <div id="fab">
            <h1>{title}</h1>
            <FloatingActionButton onClick={onClick}>
               {children}
            </FloatingActionButton>
         </div>
      )
   }
)
SomeView.propTypes = {
   onClick: PropTypes.func,
}
SomeView.defaultProps = {
   onClick: () => {},
}
import ReactDOM from 'react-dom'

var foo = React.createElement('li', null, 'First Text Content');
ReactDOM.render(foo, document.getElementById('example'));

exemple complet en classe ES6

import React, { Component, Fragment } from 'react'
import PropTypes from 'prop-types'
import ReactDOM from 'react-dom'

// https://facebook.github.io/react/docs/reusable-components.html
class CoolComponent extends React.Component {
   static propTypes = {
      ...
   }
   static defaultProps = {
      initialCount: 0
   }

   state = {
      ...
   }

   constructor (props) {
      console.info('~~ constructor', arguments)
      super(props)
   }

	// inheriting :
	// .state => NEVER mutate this.state directly, treat this.state as if it were immutable.
	// this.setState(state => ({bubbles: state.bubbles.slice(0, -1)})) XXX asynchronous, don't expect this.state to mutate immediately
	// .replaceState(nextState, [callback]) XXX do not use, pending removal
	// .forceUpdate([callback])
	// setProps


	// NO "This is only supported for classes created using React.createClass.
	// Did you mean to define a state property instead?"
	/*getInitialState () {
		console.info('~~ getInitialState', arguments)
		return {
			foo: 42
		}
	}*/

	// NO "This is only supported for classes created using React.createClass.
	// Use a static property to define defaultProps instead."
	/*getDefaultProps () {
		console.info('~~ getDefaultProps', arguments)
		return {
			value: 'default value'
		}
	}*/

	// invoked once
	componentWillMount () {
		console.info('~~ componentWillMount', arguments)

	}

	render () {
		console.count('~~ render')
		console.info('~~ render', arguments)
		return (
			<p>
				Hello, <input type="text" placeholder="Your name here" /> !<br />
				{this.props.children}
			</p>
		)
	}

	// invoked once, client only
	componentDidMount () {
		console.info('~~ componentDidMount', arguments)

	}

	// https://facebook.github.io/react/docs/component-specs.html#updating-componentwillreceiveprops
	// REM : props may NOT have changed
	// cf. https://facebook.github.io/react/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html
	componentWillReceiveProps (nextProps) {
		console.info('~~ componentWillReceiveProps', arguments)

	}

	// https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate
	shouldComponentUpdate (nextProps, nextState) {
		console.info('~~ shouldComponentUpdate', arguments)
		return true // optimisation possible
	}

	// https://facebook.github.io/react/docs/component-specs.html#updating-componentwillupdate
	// REM : NOT called in the initial rendering
	componentWillUpdate (nextProps, nextState) {
		console.info('~~ componentWillUpdate', arguments)
		return true // optimisation possible
	}

	// https://facebook.github.io/react/docs/component-specs.html#updating-componentdidupdate
	componentDidUpdate (prevProps, prevState) {
		console.info('~~ componentDidUpdate', arguments)

	}

	// https://facebook.github.io/react/docs/component-specs.html#unmounting-componentwillunmount
	componentWillUnmount () {
		console.info('~~ componentWillUnmount', arguments)

	}
}

// CoolComponent.mixins

// CoolComponent.statics


ReactDOM.render(
	<CoolComponent />,
	document.getElementById('example')
)

exemple complet en classe typescript

import React from 'react'
import PropTypes from 'prop-types'

export interface State {
}

export interface Props {
  children?: React.ReactNode[]
}

export class CoolComponent extends React.Component<Props, State> {

	public constructor(props: Props) {
		super(props)
		this.state = { ... }
	}

	public componentWillMount () {}
	public render () {}
	public componentDidMount () {}
	public componentWillReceiveProps (nextProps: Props) {}
	public shouldComponentUpdate (nextProps: Props, nextState: State) {}
	public componentWillUpdate (nextProps: Props, nextState) {}
	public componentDidUpdate (prevProps: Props, prevState) {}
	public componentWillUnmount () {}
}

JSX

// To render an HTML tag, just use lower-case tag names in JSX:

var myDivElement = <div className="foo" />;
ReactDOM.render(myDivElement, document.getElementById('example'));

// To render a React Component, just create a local variable that starts with an upper-case letter:

var MyComponent = React.createClass({/*...*/});
var myElement = <MyComponent someProperty={true} />;
ReactDOM.render(myElement, document.getElementById('example'));

// React's JSX uses the upper vs. lower case convention to distinguish between local component classes and HTML tags.

Attribute Expressions, Boolean Attributes, Child Expressions, Comments :

<Person name={window.isLoggedIn ? window.name : ''} />
<input type="button" disabled={true} />
<Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>
  <Nav>
    {/* child comment, put {} around */}
    <Person
      /* multi
         line
         comment */
      name={window.isLoggedIn ? window.name : ''} // end of line comment
    />
  </Nav>

HTML Entities, Custom HTML Attributes

<div dangerouslySetInnerHTML={{__html: 'First &middot; Second'}} />
<div data-custom-attribute="foo" />

props

passer les props

  1. une par une return <tileSimple image={x.jpg} legend='foo' />
  2. toutes d'un coup return <tileSimple {...tile} /> http://stackoverflow.com/a/26860030/587407
  3. plus complexe : héritage de props : https://facebook.github.io/react/docs/transferring-props.html

accéder aux props

this.props

propTypes

import PropTypes from 'prop-types'

PropTypes.bool,
PropTypes.func,
PropTypes.number,
PropTypes.object,
PropTypes.string,
PropTypes.element, // A React element.
PropTypes.node, // Anything that can be rendered: numbers, strings, elements or an array (or fragment) containing these types

PropTypes.array,
PropTypes.arrayOf(PropTypes.number),


// You can also declare that a prop is an instance of a class. This uses JS's instanceof operator.
PropTypes.instanceOf(Message),

// You can ensure that your prop is limited to specific values by treating it as an enum.
PropTypes.oneOf(['News', 'Photos']),

// An object that could be one of many types
PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.number,
      PropTypes.instanceOf(Message)
]),

// An object with property values of a certain type
PropTypes.objectOf(PropTypes.number),

// An object taking on a particular shape
PropTypes.shape({
      color: PropTypes.string,
      fontSize: PropTypes.number
}),

// You can chain any of the above with `isRequired` to make sure a warning is shown if the prop isn't provided.
PropTypes.func.isRequired,

// A value of any data type
requiredAny: PropTypes.any.isRequired,

custom possible.

State

refs

https://facebook.github.io/react/docs/more-about-refs.html

recettes

context

https://reactjs.org/docs/context.html

cloning

let children = state.children.map(c => c.element)
	children = React.Children.map(children, (child, index) => {
		return (typeof child === 'string')
			? child
			: React.cloneElement(child, {key: `${index}`})
	})

const children = React.Children.map(this.props.children, child => {
        const { value } = child.props
          return React.cloneElement(child, {
              isActive: value === this.state.value,
              onClick: () => {console.log(value); this.setState({value})},
          })
      })

test

Voir enzyme

Avancé

TypeScript

Available types:

  • ElementType<P = any> = (some complex intrinsic stuff) | ComponentType<P>
    • deprecated type ReactType<P = any> = ElementType<P>
    • deprecated type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P>
  • ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
  • interface Component<P = {}, S = {}, SS = any>
  • Ref<T>
  • interface FunctionComponentElement<P> extends ReactElement<P, FunctionComponent<P>> { …
  • interface ReactComponentElement<…> extends ReactElement<P, T> { }

create-react-app

https://medium.com/curated-by-versett/dont-eject-your-create-react-app-b123c5247741

perfs / optimisation

https://facebook.github.io/react/docs/advanced-performance.html

PureRenderMixin

stack

react n'est qu'un composant, il faut bâtir sa stack. Recommendations ?

Bons:

À voir:

react-router

https://github.com/reactjs/react-router

Cascading routes:

  • Top
import { Router, hashHistory } from 'react-router'
import { routes } from './routes'

<Router history={hashHistory}>
  { routes() }
</Router>
  • routes
import SubAppRoutes from '../subapp/routes'

export function routes() {
  return (
    <Route>
      <Route path='dependencies'
        component={Dependencies} />
      <Route path='download'
        component={Download} reducer={downloadReducer} />

      {WebAppRoutes() }

    </Route>
  )
}

react-testing-library

react native

Problèmes rencontrés

Common https://dev.to/samerbuna/reactjs-frequently-facedproblems--l5g

Unknown DOM property class. Did you mean className

Utiliser className http://stackoverflow.com/questions/30968113/warning-unknown-dom-property-class-did-you-mean-classname

Uncaught Error: Invariant Violation

http://stackoverflow.com/questions/25026399/uncaught-error-invariant-violation-findcomponentroot-110-unable-to

À trier

⚠️ **GitHub.com Fallback** ⚠️