четверг, 25 августа 2016 г.

React My CheatSheet

// React

import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(<App />, document.getElementById('root'));

class App extends Component {
    render () {
        return (
            {/* Это комментарий к компоненту */}
            <div id="app"> // а это комментарий в конце строки
                <p>{     }Так{     }вставляется{     }множество{     }пробелов{     }</p>
                <Header identificator="header" func={function () {console.log('OK');}}>Главное меню</Header>
                <DangerousHTML />
                <Menu />
                <Form />
                <PropsValidation />
                <Lifecycle />
            </div>
        );
    }
}

class Header extends Component {
    render () {
        this.props.func();
        <h1 className={this.props.identificator === 'header' ? 'bold' : 'thin'}
               style={{backgroundColor: 'red', color: 'blue'}}
               data-custom-attribute="foo"
        >this.props.children</h1>
    }
}

class DangerousHTML extends Component {
    render () {
        return (
            <div dangerouslySetInnerHTML={{__html: '<span>&middot; Это опасный HTML-код</span>'}}></div>
        );
    }
}

class Menu extends Component {
    render () {
        const elements = [
              ['главная', '/']
            , ['отчеты', '/reports']
            , ['контакты', '/contacts']
        ];
        return (
            <List elementsArray={elements} />
        );
    }
}

class List extends Component {
    render () {
        <ul>
            {this.props.elementsArray.map((element, index) => {
                return (
                    <li key={index}><a href={element[1]} onClick={this.handleClick.bind(this)}>{element[0]}</a></li>
                );
            })}
        </ul>
    }
    handelClick (event) {
        event.preventDefault();
        console.log(event.target.innerHTML);
    }
}

class Form extends Component {
    constructor (props) {
        super(props);
        this.state = {
              inputValue: 'Анна'
            , textareaValue: 'Пришла на работу'
            , selectValue: 'one'
            , checkboxValue: true
        };
    }
    render () {
        return (
            <form method="get" action="/" onSubmit={this.handleSubmit.bind(this)}>
                <label htmlFor="input">Имя</label>
                <input ref="inputRef" type="text" disabled={false} defaultValue="Борис" value={this.state.inputValue} onChange={this.handleInputChange.bind(this)} />
                <textarea ref="textareaRef" disabled={false} defaultValue="Идет домой" value={this.state.textareaValue} onChange={this.handleTextareaChange.bind(this)} />
                <select ref="selectRef" disabled={false} multiple={true} value={selectValue} {/* или value={[selectValue, 'two']} */}  onChange={this.handleSelectChange.bind(this)}>
                    <option value="one">один</option>
                    <option value="two">два</option>
                    <option value="three">три</option>
                </select>
                <input ref="checkboxRef" type="checkbox" disabled={false} checked={this.props.checkboxValue} onChange={this.handleCheckboxChange.bind(this)} />{' '}Всё разрешено
                <input type="submit" value="Найти" />
                <input type="clear" value="Очистить" />
            </form>
        );
    }
    handleInputChange (event) {
        this.setState(Object.assing({}, this.state, {inputValue: event.target.value > 5 ? event.target.value.slice(0, 5) : event.target.value}));
    }
    handleTextareaChange (event) {
        this.setState(Object.assing({}, this.state, {textareaValue: event.target.value}));
    }
    handleSelectChange (event) {
        console.log(event.target.value);
    }
    handleCheckboxChange (event) {
        this.setState(Object.assing({}, this.state, {checkboxValue: event.target.checked === true ? 'checked' : ''}));
    }
    handleSubmit (event) {
        event.preventDefault();
        $.ajax({
              url: '/send'
            , type: 'POST'
            , data: {
                  input: this.refs.inputRef.value
                , textarea: this.refs.textareaRef.value
                , select this.refs.selectRef.value
                , checkbox: this.refs.checkboxRef.checked
              }
            , dataType: 'json'
            , success: function () {
                this.setState(Object.assign({}, this.state, {
                      inputValue: ''
                    , textareaValue: ''
                    , selectValue: ''
                    , checkboxValue: false
                }));
              }.bind(this)
            , error: function () {}.bind(this)
        });
    }
    handleClear (event) {
        event.preventDefault();
        this.state = {
              inputValue: ''
            , textareaValue: ''
            , selectValue: ''
            , checkboxValue: true
        };
    }
}

class PropsValidation extends Component {
    static defaultProps = {
          optionalBoolean: true
        , optionalNumber: 1
        , optionalString: 'text'
    }
    static propTypes = {
          optionalBoolean: PropTypes.bool

        , optionalNumber: PropTypes.number

        , optionalString: PropTypes.string
        , optionalOneOf: PropTypes.oneOf(['News', 'Photos'])

        , optionalArray: PropTypes.array
        , optionalArrayOf: PropTypes.arrayOf(PropTypes.number)

        , optionalObject: PropTypes.object
        , optionalObjectOf: PropTypes.objectOf(PropTypes.number)
        , optionalObjectWithShape: PropTypes.shape({color: PropTypes.string, fontSize: PropTypes.number})

        , optionalFunction: PropTypes.func
        , requiredFunction: PropTypes.func.isRequired

        , optionalSymbol: PropTypes.symbol

        , optionalReactElement: PropTypes.element

        , anythingOptionalThatCanBeRendered: PropTypes.node

        , optionalInstanceOfClass: PropTypes.instanceOf(Array)

        , optionalOneOfType: PropTypes.oneOfType([PropTypes.number, PropTypes.string])

        , requiredAny: PropTypes.any.isRequired

        , customProp: function (props, propName, componentName) {
            if (!/matchme/.test(props[propName])) {
                return new Error('Invalid prop "' + propName + '" supplied to "' + componentName + '". Validation failed.');
            }
        }
    }
    render () {
        return (
            <div>
                {this.props.optionalBoolean}
                {this.props.optionalNumber}
                {this.props.optionalString}
                {this.props.optionalOneOf}
                {this.props.optionalArray}
                {this.props.optionalArrayOf}
                {this.props.optionalObject}
                {this.props.optionalObjectOf}
                {this.props.optionalObjectWithShape}
                {this.props.optionalFunction()}
                {this.props.requiredFunction()}
                {this.props.optionalSymbol}
                {this.props.optionalReactElement}
                {this.props.anythingOptionalThatCanBeRendered}
                {this.props.optionalInstanceOfClass}
                {this.props.optionalOneOfType}
                {this.props.requiredAny}
                {this.props.customProp}
            </div>
        );
    }
}

class Lifecycle extends Component {
    /* componentWillMount (props) { */ constructor (props) { // Установка первоначальных значений - выполняется 1 раз перед вставкой компонента на страницу
        super(props);
        /* getInitialState () {return {comments: []};} */ this.state = {comments: []};
        this.intervals = [];
    }
    setInterval: function() {
        this.intervals.push(setInterval.apply(null, arguments));
    }
    render () { // Вызывается при вставке компонента на страницу и каждый раз при изменении свойств this.props и состояния через this.setState()
        if (this.state.comments.length > 0) {
            return (
                <ul className="comments">
                    {this.state.comments.map((comment) => {
                        return (
                            <li>comment</li>
                        );
                    })}
                </ul>
            );
        } else {
            return (
                <p>Нет данных</p>
            );
        }
    }
    componentDidMount () { // Вызывается только 1 раз после того, как компонент будет вставлен на страницу - можно изменять рамеры элементов после вставки компонента или для получения данных через AJAX
        getData().then((data) => {
            this.setState({comments: data});
        });
        resizeComponent();
        this.setInterval(this.tick, 1000);
    }
    componentWillReceiveProps (nextProps) { // Вызывается, когда уже вставленный на страницу компонент перезагружается и получает новые свойства props - обычно не нужно менять
        this.setState(Object.assign({}, this.state, {comments: nextProps.comments}));
    }
    shouldComponentUpdate (nextProps, nextState) { // Вызывается каждый раз перед перерисовкой компонента - обычно не нужно менять
        // return nextProps.id !== this.props.id;
        if (this.state.comments.length > 0) {
            return true;
        } else {
            return false;
        }
    }
    componentWillUpdate () { // Вызывается многократно перед обновлением содержимого компонента на странице - можно устанавливать слушатели событий
        console.log('All data is valid');
    }
    componentDidUpdate () { // Вызывается многократно после обновления содержимого компонента на странице - можно изменять рамеры элементов после вставки компонента
        resizeComponent();
    }
    componentWillUnmount () { // Удаление слушаетелей событий перед удалением компонента из содержимого страницы
        this.intervals.forEach(clearInterval);
    }
}

Комментариев нет:

Отправить комментарий