Some TILs about programming, photography and other stuff.

React JS

👉 Gatsby

👉 Next.js by Vercel - The React Framework

👉 GitHub - AlexGilleran/jsx-control-statements: Neater If and For for React JSX

Conceptos básicos

Props vs state

Props é un obxeto con valores inmutables, mentres que state pode variar. State é o obxeto que se modifica para reflexar os cambios no navegador. Os compoñentes poden cambiar o seu estado interno, pero non as suas propiedades.

Compoñentes

function Button() {
	return <button>TEST</button>
}

ReactDOM.render(
  <Button />,
  document.getElementById('mountNode'),
);

Deben ir en maiúsculas, xa que si non React tomaraos como elementos HTML. Por exemplo, da seguinte forma ignoraría o compoñente button e poñería un button HTML:

function button() {
	return <button>TEST</button>
}

ReactDOM.render(
  <button />,
  document.getElementById('mountNode'),
);

Eventos

Por exemplo no seguinte caso, para controlar o evento de click:

Podemos pasar a referencia a función. Sen o (), xa que os parénteses son para executala e de esa forma non funcionaría.

function logRandom() {
  console.log(Math.random())
}
function Button() {
  const [counter, setCounter] = useState(0)
	return <button onClick={logRandom}>{counter}</button>;
}
ReactDOM.render(
  <Button />,
  document.getElementById('mountNode'),
);

Ou pode definirse a función directamente. En este caso de exemplo emprégase o formato de arrow function, pero tamén funcionaría tamén con función normal:

function Button() {
  const [counter, setCounter] = useState(0)
	return <button onClick={() => setCounter(counter + 1)}>{counter}</button>;
}
ReactDOM.render(
  <Button />,
  document.getElementById('mountNode'),
);

En este outro exemplo defínese a función que manexa o evento dentro do compoñente para que teña acceso aos métodos:

function Button() {
	const [counter, setCounter] = useState(0);
  const handleClick = () => setCounter(counter+1)
	return(
    <button onClick={handleClick}>
      {counter}
    </button>
  );
}

ReactDOM.render(
  <Button />,
  document.getElementById('mountNode'),
);

Si temos dous compoñente que deben compartir datos debe facerse a través do compoñente pai, para iso podemos facer o que se fai neste exemplo:

function Button(props) {
	return(
    <button onClick={props.onClickFunction}>
      +1
    </button>
  );
}

function Display(props) {
  return(
    <div>{props.message}</div>
  )
}

function App() {
  const [counter, setCounter] = useState(42);
  const incrementCounter = () => setCounter(counter + 1)
  return(
    <>
      <Button onClickFunction={incrementCounter}/>
      <Display message={counter} />
    </>
  )
}

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

O compoñente App manexa o estado. A Button pásalle a referencia da función que modifica o estado ao facer click e a Display pásalle o valor de counter para que o mostre.

Parámetros nunha función de control de evento

Si a función que responde ao evento onClick en button precisa que lle pasemos algún parámetro debemos crear unha nova función, xa que en ese punto non se pode empregar (), porque a estaríamos invocando. Este sería o exemplo que contén a función do compoñente Button duplicada con dúas formas de resolvelo:

// Forma de resolvelo 1
function Button(props) {
  const handleClick = () => props.onClickFunction(props.increment)
	return(
    <button onClick={handleClick}>
      +{props.increment}
    </button>
  );
}

// Forma de resolvelo 2
function Button(props) {
	return(
    <button onClick={() => props.onClickFunction(props.increment)}>
      +{props.increment}
    </button>
  );
}

function Display(props) {
  return(
    <div>{props.message}</div>
  )
}

function App() {
  const [counter, setCounter] = useState(0);
  const incrementCounter = (incrementValue) => setCounter(counter + incrementValue)
  return(
    <>
      <Button onClickFunction={incrementCounter} increment={1}/>
      <Button onClickFunction={incrementCounter} increment={5}/>
      <Button onClickFunction={incrementCounter} increment={10}/>
      <Button onClickFunction={incrementCounter} increment={100}/>
      <Display message={counter} />
    </>
  )
}

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

Sintaxe de clase vs sintaxe de función

// Sintaxsis de clase
class App extends React.Component {
  render() {
    return <div className="header">{this.props.title}</div>
  }
}

// Sintaxis de función
const App = ({title}) => (
  <div className="header">{title}</div>
);

ReactDOM.render(
	<App title="The GitHub Cards App" />,
  mountNode,
);

Referencias

👉 Referencias y el DOM - React

Exemplo de uso de referencia:

class Form extends React.Component {
  // Creamos unha referencia que usaremos para acceder ao contido do input
  // esta referencia pásaselle ao input do formulario a través do atributo ref
  userNameInput = React.createRef()
  handleSubmit = (event) => {
    event.preventDefault()
		// Aquí recupérase o valor do input
    console.log(this.userNameInput.current.value)
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input
          type="text"
          placeholder="Github username"
          ref={this.userNameInput}
          required
        />
        <button>Add card</button>
      </form>
    )
  }
}

👉 React. El hook useRef

👉 The Github Cards App

👉 The Star Match Game

React context

📄 How to Use React Context to Share Data between Components - Pluralsight (PDF)