ranyeli
11/15/2017 - 8:18 PM

React basic files

Main files to begging using react

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

class ExpandProps extends Component {
    render(){
        return(
            <div>
                <Btns >
                    <button>A</button>
                    <button>B</button>
                    <button>C</button>
                </Btns>
            </div>
        );
    }
}

class Btns extends Component {

    constructor(){
        super();
        this.state = {
            selected: 'None'
        };
    }

    selectedBtn(selected){
        this.setState({selected: selected});
        // console.log(e, ctx.props.children);
    }

    render(){
        // function that assigns props to the children elements of this element by extending them using React.cloneElement
        // the first paramater for the bind method in functions binding is to give context, if no other paramater is given then it will also be passed as a variable, but-
        // if another parameter is given then the first this will only be used to set the context and from the second one and on they will be used as variables passed
        let expandFn = (child) => React.cloneElement(child, {prop1: 'first property', onClick: this.selectedBtn.bind(this, child.props.children)});

        // return an array of the children and pass a fn to make some modifications
        let items = React.Children.map(this.props.children, expandFn);
        return(
            <div>
                {/* set the value for the state */}
                <h1>You selected the btn <strong>{this.state.selected}</strong></h1>
                {/* contain the children for this element */}
                {items}
            </div>
        );
    }
}

export default ExpandProps;
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <!-- <link rel="stylesheet" href="%PUBLIC_URL%/style.css" > -->
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id=container>
      <!-- <div id="root" class="column"></div> -->
      <div id="any" class="column"></div>
      <div id="tomount" class="column"></div>
      <div id="HOC" class="column"></div>
      <div id="exprops" class="column"></div>
    </div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>
import React, { Component } from 'react';
// import ReactDOM  from 'react-dom';

// function that return a components and adds a common functionality, this is known as Higher Order Component.
// The React tag class/component should always beggin with an uppercase letter
const HOCfunc = (ArgComponent) => class extends Component {
    constructor(){
        super();
        this.state = {
            counter: 0
        }
    }

    updateCounter(){
        this.setState({
            counter: this.state.counter + 1
        });
    }

    componentWillMount(){
      console.log("ArgComponent is getting mounted");
    }
    

    render(){
        return(
            // by using '...' we are passing the properties set by the component when used.
            // anything passed as an attribute becomes a property including the states
            <ArgComponent 
                {...this.props}
                {...this.state}
                update={this.updateCounter.bind(this)}
            />
        );
    }
}


class HOC extends Component
{
    // rendering the Btn and TxtArea component using a Higher Order Components
    render(){
        return(
            <div>
                <h1>Higher Order Component</h1>
                <BtnHOC>Hola</BtnHOC>_______________<TxtAreaHOC>Bye</TxtAreaHOC>
            </div>
        );
    }
}

class Btn extends Component {
    render(){
        return(
            <button onClick = {this.props.update} >{this.props.children} - {this.props.counter}</button>
        );
    }
}

class TxtArea extends Component{
    render(){
        let desc = this.props.children + " - " + this.props.counter;
        return(
            // cannot set the textarea description using enclosing tags but using the 'value' or 'defaultValue' property 
            <textarea onClick = {this.props.update} value = {desc} onChange = {() => true} />
        );
    }
}

// creating components that share functionality by usiong Higher Order Component
const BtnHOC = HOCfunc(Btn);
const TxtAreaHOC = HOCfunc(TxtArea);

export default HOC;
import React, { Component } from 'react';
import ReactDOM  from 'react-dom';
import PropTypes  from 'prop-types';

class Any extends Component {
    constructor(){
        super();
        this.state = {
            st: "state obj",
            currentE: "-------",
            a: '',
            b: '',
            items: []
        };

        // Here I declare the method and set the method argument to the obj this which represent the current event in the current tag
        this.updateE = this.updateE.bind(this);
        // this.update = this.update.bind(this);
    }
    // custom method/function to manage the states
    update(e){
        // to update the states you must use the setState method and pass an object with all the states to update
        this.setState({st: e.target.value});
    }

    updateE(e){
        this.setState({currentE: e.type});
    }

    updateRef(){
        this.setState({
            a: this.refs.a.value,
            b: this.b.value
        });
    }

    // triggers when a component will be mounted to the DOM
    componentWillMount(){
      console.log("almost mounted!");
    //   populating a an state named items
      fetch('https://swapi.co/api/people/?format=json')
      .then(r => r.json()).then(_ => this.setState({items: _.results}))
      .then(_ => console.log(this.state.items));

    //   .then(({results: items}) => this.setState({items}))
    }

    // triggers when the component is already mounted to the DOM
    componentDidMount(){
      console.log("already mounted!!");
    }
    
    mount(){
        // renders a class tag in the DOM
        ReactDOM.render(<ToMount />, document.getElementById('tomount'));
    }

    unmount(){
        // unmount the component that was rendered in that DOM
        ReactDOM.unmountComponentAtNode(document.getElementById('tomount'));
    }  

    componentWillReceiveProps(nextProps) {
        // nextProps has the value that the prop will receive
        console.log(nextProps.num, "----" ,this.props.num);
    }

    increaseN(){
        // re-render this class tag or component with a new value fro the 'num' property
        ReactDOM.render(<Any num = {this.props.num * 2} />, document.getElementById('any'));
    }

    // by returning a boolean from comparing nextProps or/and nextState it allows or prevents th rendering. 'true' renders, 'false' do not.
    shouldComponentUpdate(nextProps, nextState){
      return true;
    }
    
    // runs if the component or class tag is rendered/updated
    componentDidUpdate(prevProps, prevState) {
        console.log(`prevProps ${prevProps.num}`);
    }
    
    filter(e){
        this.setState({filter: e.target.value});
    }

    render(){
        console.log("rendered!");
        let items = this.state.items;
        // filters the array by asking if it includes the characters typed in the input
        if(this.state.filter){
            items = items.filter(item => item.name.toLowerCase().includes(this.state.filter.toLowerCase()));
        }
        return(
            <div>
                <strong>Blah blah coding! {this.props.need} or {this.props.text} and {this.props.num}</strong>
                <br />
                {/* binding that pass the input object to the update method */}
                <input type="text" onChange={this.update.bind(this)} />

                {/* another way using stateless element or class element */}
                <Widget update={this.update.bind(this)} />
                <br />
                <em>This is the {this.state.st}</em> <Btn>El hijo</Btn>
                <br />
                <br />

                {/* this way I can just pass the methods without defining the binding in the tag itself */}
                <textarea
                    onKeyPress = {this.updateE}
                    onCut = {this.updateE}
                    onPaste = {this.updateE}
                    onCopy = {this.updateE}
                    // onSelect = {this.updateE}
                ></textarea> <br />
                <strong>{this.state.currentE}</strong>
                <br />
                <br />
                
                <br />
                <br />
                {/* updating several states with the same method by using references (ref) */}
                <input type="text" onChange={this.updateRef.bind(this)} ref="a" /> <u>{this.state.a}</u> <br />
                <input type="text" onChange={this.updateRef.bind(this)} ref={n => this.b = n} /> <u>{this.state.b}</u>

                <br />

                <button onClick={this.mount.bind(this)} >Mount</button>
                <button onClick={this.unmount.bind(this)} >UnMount</button> <br /> <input type="button" value={this.props.num} onClick={this.increaseN.bind(this)} />

                <div>
                    <input type="text" onChange={this.filter.bind(this)} />
                    {/* using map to render a list of items from an api*/}
                    {/* do not forget to add a key attribute to child tag using the id or any other identificator */}
                    {items.map((item, id) => <h4 key={id}>{item.name}</h4>)}
                </div>
            </div>
        );
    }
}

Any.propTypes = {
    text: PropTypes.string,
    num: PropTypes.number.isRequired
};

Any.defaultProps = {
    text: "Love",
    num: 1
};

// child component are similar to class tag but stateless and can pass attributes as parameters
const Widget = (props) => <input type="text" onChange={props.update} />;

// I could've created a class if I wanted to, instead of a stateless element
const Btn = (props) => <button>{props.children}</button>;

class ToMount extends Component {

    componentDidMount(){
        // logs the DOM rendered by this class tag
        console.log("ToMount mounted", ReactDOM.findDOMNode(this));
    }

    componentWillMount(){
        console.log("ToMount unmounted");
    }

    render(){
        return(
            <button>Montado... :D</button>
        )
    }
}

export default Any;
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// import App from './App';
import Any from './Any';
import HOC from './HOC';
import ExpandProps from './ExpandProps';

import registerServiceWorker from './registerServiceWorker';

// ReactDOM.render(<App />, document.getElementById('root'));
ReactDOM.render(<Any need = "sex" />, document.getElementById('any'));
ReactDOM.render(<HOC />, document.getElementById('HOC'));
ReactDOM.render(<ExpandProps />, document.getElementById('exprops'));

registerServiceWorker();