import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class Boton extends Component { mas = () => { this.props.mas(0); } render() { return ( <button onClick={this.mas}>+</button> ); } } ; class Fila extends Component { menos = () => { this.props.menos(this.props.indice); } render() { return ( <p><input type="number" value={this.props.valor}></input> <button onClick={this.menos}>-</button> </p> ); } } class Total extends Component { render() { return ( <p>Total:{this.props.suma}</p> ) } } class Tabla extends Component { constructor(props) { super(props); this.state = { numeros: [1, 2, 90, 0, 45] }; } mas = (valor) => { this.setState({ numeros: [...this.state.numeros, valor] }); } menos = (index) => { this.setState({ numeros: this.state.numeros.filter((numero, i) => i != index) }); } render() { const filas = this.state.numeros.map((valor, index) => { return (<Fila key={index} indice={index} valor={valor} menos={this.menos} />); }); const suma = this.state.numeros.reduce((a, b) => a + b, 0); return ( <div> <Boton mas={this.mas} /> {filas} <Total suma={suma} /> </div> ); } } ; class App extends Component { render() { return ( <Tabla /> ); } } ; export default App;
Etiqueta color
import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class Cuadrado extends Component { render() { const estilo = { padding: 10, margin: 20, display: "inline-block", backgroundColor: this.props.bgColor, width: 100, height: 100 }; return ( <div style={estilo}> </div> ); } } class Color extends Component { constructor(props) { super(props); this.state = { color: this.props.color }; } cambio = (event) => { const {name, value} = event.target; this.setState({ [name]: value }) this.props.cambiaColor(value); } render() { return ( <div> <input type="text" name="color" value={this.state.color} onChange={this.cambio}/> </div> ); } } class Tarjeta extends Component { constructor(props) { super(props); this.state = { color: "red" }; } isColor = (strColor) => { const s = new Option().style; s.color = strColor; return s.color !== ''; } shouldComponentUpdate(nextProps, nextState) { return this.isColor(nextState.color); } cambiaColor = (color) => { this.setState({color: color}); } render() { return ( <div> <Cuadrado bgColor={this.state.color}/> <Color color={this.state.color} cambiaColor={this.cambiaColor}/> </div> ); } } ; class App extends Component { render() { return ( <Tarjeta/> ); } } export default App;
Ciclo de vida de los componentes
Aquí están muy bien explicados:
https://www.gistia.com/understand-react-lifecycle-methods/
Código:
import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import logo from './logo.svg'; import './App.css'; class Contador extends React.Component { render() { var textStyle = { fontSize: 72, fontFamily: "sans-serif", color: "#333", fontWeight: "bold" }; console.log("render: Contador componente"); return ( <div style={textStyle}> {this.props.display} </div> ); } } class ContadorParent extends React.Component { constructor(props) { super(props); console.log("constructor: Valores por defecto"); this.state = { count: 0 }; this.increase = this.increase.bind(this); } increase() { this.setState({ count: this.state.count + 1 }); } static getDerivedStateFromProps(props, state) { console.log("getDerivedStateFromProps: Poco uso") return null; } componentDidUpdate(currentProps, currentState) { console.log("componentDidUpdate: El componente se ha actualizado"); } getSnapshotBeforeUpdate(prevProps, prevState) { console.log("getSnapshotBeforeUpdate: El componente va a enviar sus cambios") return null; } componentDidMount() { console.log("componentDidMount: Componente insertado en el árbol DOM"); } componentWillUnmount() { console.log("componentWillUnmount: Component a punto de ser eliminado del DOM"); } shouldComponentUpdate(newProps, newState) { console.log("shouldComponentUpdate: ¿Hay que actualizar?"); if (newState.count < 5) { console.log("shouldComponentUpdate: Sí, hay que actualizar"); return true; } else { ReactDOM.unmountComponentAtNode(document.getElementById('root')); console.log("shouldComponentUpdate: No hay que actualizar"); return false; } } render() { var backgroundStyle = { padding: 50, border: "#333 2px dotted", width: 250, height: 100, borderRadius: 10, textAlign: "center" }; console.log("render: ContadorParent componente"); return ( <div style={backgroundStyle}> <Contador display={this.state.count} /> <button onClick={this.increase}> + </button> </div> ); } } ; class App extends Component { render() { return ( <ContadorParent/> ); } } ; export default App;
Formulario
import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class Form extends Component { constructor(props) { super(props) this.initialState = { nombre: '', nota: '', } this.state = this.initialState; } cambio = event => { const {name, value} = event.target; console.log(name + "|" + value); this.setState({ [name]: value }) } enviar = () => { this.props.mas(this.state.nombre, this.state.nota); this.setState(this.initialState); } render() { return ( <form> <label>Nombre</label> <input type="text" name="nombre" value={this.state.nombre} onChange={this.cambio} /> <label>Nota</label> <input type="text" name="nota" value={this.state.nota} onChange={this.cambio} /> <input type="button" onClick={this.enviar} value="Añadir"/> </form> ); } } class Cabecera extends Component { render() { return ( <tr><th>Alumno</th><th>Nota</th></tr> ); } } ; class Fila extends Component { eliminar=(e)=>{ e.stopPropagation(); this.props.menos(this.props.indice); } render() { return ( <tr onClick={() => this.props.mas(this.props.nombre, this.props.nota)}> <td>{this.props.nombre}</td><td>{this.props.nota}</td> <td><input type="button" value="Borrar" onClick={this.eliminar}/></td> </tr> ); } } ; class Tabla extends Component { constructor(props) { super(props); this.state = { alumnos: this.props.alumnos, cont: 0 }; this.mas = this.mas.bind(this); } mas(nombre, nota) { this.setState({alumnos: [...this.state.alumnos, {nombre: nombre, nota: nota}]}); } menos = (index) => { this.setState({ alumnos: this.state.alumnos.filter((alumno, i) => i != index) }); } render() { const filas = this.state.alumnos.map((fila, index) => { return (<Fila key={index} indice={index} nombre={fila.nombre} nota={fila.nota} menos={this.menos} mas={this.mas}/>); } ); return ( <div> <Form mas={this.mas}/> <button onClick={() => this.mas("Ana", 6)}>Añadir</button> <button onClick={() => this.menos(0)}>Quitar</button> <table> <thead> <Cabecera/></thead> <tbody> {filas} </tbody> </table> </div> ); } } ; class App extends Component { render() { const alumnos = [{nombre: "Ana", nota: 6}, {nombre: "Pep", nota: 4}, {nombre: "Eva", nota: 8}, {nombre: "Ot", nota: 7}]; return ( <Tabla alumnos={alumnos}/> ); } } ; export default App;
Quitar elementos
import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class Cabecera extends Component { render() { return ( <tr><th>Alumno</th><th>Nota</th></tr> ); } } ; class Fila extends Component { render() { return ( <tr onClick={() => this.props.mas(this.props.nombre, this.props.nota)}> <td>{this.props.nombre}</td><td>{this.props.nota}</td> </tr> ); } } ; class Tabla extends Component { constructor(props) { super(props); this.state = { alumnos: this.props.alumnos, cont: 0 }; this.mas = this.mas.bind(this); } mas(nombre, nota) { this.setState({alumnos: [...this.state.alumnos, {nombre: nombre, nota: nota}]}); } menos=(index)=>{ this.setState({ alumnos:this.state.alumnos.filter((alumno,i)=>i!=index) }); } render() { const filas = this.state.alumnos.map((fila, index) => { return (<Fila key={index} nombre={fila.nombre} nota={fila.nota} mas={this.mas}/>); } ); return ( <div> <button onClick={() => this.mas("Ana", 6)}>Añadir</button> <button onClick={() => this.menos(0)}>Quitar</button> <table> <thead> <Cabecera/></thead> <tbody> [ {filas} </tbody> </table> </div> ); } } ; class App extends Component { render() { const alumnos = [{nombre: "Ana", nota: 6}, {nombre: "Pep", nota: 4}, {nombre: "Eva", nota: 8}, {nombre: "Ot", nota: 7}]; return ( <Tabla alumnos={alumnos}/> ); } } ; export default App;
Pasar funciones a componentes hijos
Un ejemplo:
import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class Cabecera extends Component { render() { return ( <tr><th>Alumno</th><th>Nota</th></tr> ); } } ; class Fila extends Component { render() { return ( <tr onClick={() => this.props.mas(this.props.nombre, this.props.nota)}> <td>{this.props.nombre}</td><td>{this.props.nota}</td> </tr> ); } } ; class Tabla extends Component { constructor(props) { super(props); this.state = { alumnos: this.props.alumnos, cont: 0 }; this.mas = this.mas.bind(this); } mas(nombre, nota) { this.setState({alumnos: [...this.state.alumnos, {nombre: nombre, nota: nota}]}); } render() { const filas = this.state.alumnos.map((fila, index) => { return (<Fila key={index} nombre={fila.nombre} nota={fila.nota} mas={this.mas}/>); } ); return ( <div> <button onClick={() => this.mas("Ana", 6)}>Añadir</button> <table> <thead> <Cabecera/></thead> <tbody> {filas} </tbody> </table> </div> ); } } ; class App extends Component { render() { const alumnos = [{nombre: "Ana", nota: 6}, {nombre: "Pep", nota: 4}]; return ( <Tabla alumnos={alumnos}/> ); } } ; export default App;
Ver círculo (II)
import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class Circulo extends React.Component { render() { var circuloStyle = { padding: 10, margin: 20, display: "inline-block", backgroundColor: this.props.bgColor, borderRadius: "50%", width: 100, height: 100, }; return ( <div style={circuloStyle}> </div> ); } } function verCirculo(num) { let colores = ["#393E41", "#E94F37", "#1C89BF", "#A1D363", "#FF2178","#e5d8bf","#00818a","#f54291","#ff0000"]; let circulos = []; for (let i = 0; i < num; i++) { let ran = Math.floor(Math.random() * colores.length); circulos.push(<Circulo key={i} bgColor={colores[ran]} />); } return circulos; } class VerCirculo extends React.Component { render() { return verCirculo(this.props.num); } } class App extends Component { constructor(props){ super(props); this.state={cont:0}; } foo=()=>{ this.setState({cont:this.state.cont+1}); } render() { return ( <div onClick={this.foo}> <VerCirculo num="3"/> {verCirculo(this.state.cont)} </div> ); } } export default App;
Ver Círculo (I)
import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class Circulo extends React.Component { render() { var circuloStyle = { padding: 10, margin: 20, display: "inline-block", backgroundColor: this.props.bgColor, borderRadius: "50%", width: 100, height: 100 }; return ( <div style={circuloStyle}> </div> ); } } function verCirculo() { let colores = ["#393E41", "#E94F37", "#1C89BF", "#A1D363"]; let ran = Math.floor(Math.random() * colores.length); return <Circulo bgColor={colores[ran]} />; } class App extends Component { render() { return ( <div> {verCirculo()}{verCirculo()}{verCirculo()} </div> ); } } export default App;