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();