Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/jantoniogc/CursoReact-Clima/llms.txt

Use this file to discover all available pages before exploring further.

Clima React App is composed of four React components. Header and Error are purely presentational. Formulario manages its own local validation state. Clima reads from the OpenWeatherMap response object and converts temperatures from Kelvin to Celsius before rendering. All components receive their data exclusively through props passed down from App.
All four components use Component.prototype = { ... } instead of Component.propTypes = { ... }. This is a bug in the original source — assigning to .prototype has no effect on React’s prop-type checking at runtime. The correct property is .propTypes. Runtime prop-type validation is therefore silently disabled across the entire app.

Header renders a Materialize CSS top navigation bar containing the app title as the brand logo text.

Props

titulo
string
required
The text displayed as the navigation bar’s brand logo. Rendered inside an <a className="brand-logo"> element.

Source

import React from 'react';
import PropTypes from 'prop-types';

const Herader = ({ titulo }) => {
  return (
    <nav>
      <div className="nav-wrapper light-blue darken-2">
        <a href='#!' className="brand-logo">{titulo}</a>
      </div>
    </nav>
  );
}

Herader.prototype = {
  titulo: PropTypes.string.isRequired
}
export default Herader;
Notable details: The component is declared as Herader (a typo of “Header”) but exported under that same name. App.js imports it as Header, which works because the import alias is independent of the variable name inside the file.

Formulario

Formulario renders a controlled form with a city text input and a country <select> dropdown. It manages its own local error boolean for empty-field validation and calls setConsultar(true) on valid submission to trigger the API call in App.

Props

busqueda
object
required
The current search state from App. Shape: { ciudad: string, pais: string }. Used to make the form inputs controlled.
setBusqueda
function
required
State setter from App. Called on every input change with the spread-updated busqueda object to lift form state up.
setConsultar
function
required
State setter from App. Called with true on valid form submission to trigger the useEffect API call in App.

Source

import React, { useState } from 'react';
import Error from './Error';
import PropTypes from 'prop-types';

const Formulario = ({ busqueda, setBusqueda, setConsultar }) => {

  const [error, setError] = useState(false);

  const { ciudad, pais } = busqueda;

  const handleChange = (e) => {
    setBusqueda({
      ...busqueda,
      [e.target.name]: e.target.value
    })
  }

  const handleSubmit = (e) => {
    e.preventDefault();
    if (ciudad.trim() === "" || pais.trim() === "") {
      setError(true);
      return;
    }
    setError(false);
    setConsultar(true);
  }

  return (
    <form onSubmit={handleSubmit}>
      {error ? <Error mensaje="Todos los campos son obligatorios"></Error> : null}
      <div className="input-field col s12">
        <input
          type="text"
          name="ciudad"
          id="ciudad"
          value={ciudad}
          onChange={handleChange}
        />
        <label htmlFor="ciudad">Ciudad:</label>
      </div>
      <div className="input-field col s12">
        <select
          name="pais"
          id="pais"
          value={pais}
          onChange={handleChange}
        >
          <option value="">-- Selecciones un Pais --</option>
          <option value="US">Estados Unidos</option>
          <option value="MX">México</option>
          <option value="AR">Argentina</option>
          <option value="CO">Colombia</option>
          <option value="CR">Costa Rica</option>
          <option value="ES">España</option>
          <option value="PE">Perú</option>
        </select>
        <label htmlFor="pais">Pais:</label>
      </div>
      <div className="input-field col s12">
        <input
          type="submit"
          className="waves-effect waves-light btn-large btn-block yellow accent-4"
          value="Buscar Cllima"
        />
      </div>
    </form>
  );
}

Formulario.prototype = {
  busqueda: PropTypes.object.isRequired,
  setBusqueda: PropTypes.func.isRequired,
  setConsultar: PropTypes.func.isRequired
}
export default Formulario;
Notable details: Formulario keeps its own error state separate from App’s error state. The local flag controls whether an inline validation message is shown; App’s error flag is only set after a failed API response.

Clima

Clima renders a Materialize card displaying the current temperature, maximum temperature, and minimum temperature for the city returned by the OpenWeatherMap API. All temperatures are converted from Kelvin to Celsius before display.

Props

resultado
object
required
The raw JSON response from the OpenWeatherMap /data/2.5/weather endpoint. The component reads resultado.name (city name string) and resultado.main (object containing temp, temp_max, and temp_min in Kelvin).

Source

import React from 'react';
import PropTypes from 'prop-types';

const Clima = ({ resultado }) => {

  const { name, main } = resultado;

  if (!name) return null;

  const kelvin = 273.15;

  return (
    <div className="card-panel white col s12">
      <div className="black-text">
        <h2>El clime de {name} es:</h2>
        <p className="temperatura">
          {parseFloat(main.temp - kelvin, 10).toFixed(2)} <span>&#x2103;</span>
        </p>
        <p>Temperatur Máxima:
          {parseFloat(main.temp_max - kelvin, 10).toFixed(2)} <span>&#x2103;</span>
        </p>
        <p>Temperatura Mínima:
          {parseFloat(main.temp_min - kelvin, 10).toFixed(2)} <span>&#x2103;</span>
        </p>
      </div>
    </div>
  );
}

Clima.prototype = {
  resultado: PropTypes.object.isRequired
}

export default Clima;
Notable details: The component guards against rendering before any API call has completed by checking if (!name) return null. On the initial render resultado is an empty object {}, so name is undefined and the component renders nothing rather than crashing.

Error

Error renders a single paragraph styled with Materialize’s red darken-4 background class and a custom error CSS class from index.css that adds padding, centers text, and forces white text color.

Props

mensaje
string
required
The error message string to display. Rendered as the text content of a <p> element.

Source

import React from 'react';
import PropTypes from 'prop-types';

const Error = ({ mensaje }) => {
  return (
    <p className="red darken-4 error">{mensaje}</p>
  );
}

Error.prototype = {
  mensaje: PropTypes.string.isRequired
}

export default Error;
Notable details: Error is used in two places: inside Formulario for empty-field validation ("Todos los campos son obligatorios") and inside App for failed API responses ("No hay resultados").

Build docs developers (and LLMs) love