Estoy construyendo un formulario en React. Dentro de este formulario tengo un componente de alerta, que muestra un mensaje de respuesta si el envío salió bien o mal.

Mi forma se ve así:

<form onSubmit={this.onSubmit}>
    {
        this.state.error &&
        <Alert text={this.state.error} />
    }
    <input
        type="text"
        placeholder="Enter link url"
        value={this.state.url}
        onChange={this.onUrlChange} />

    <button type="submit">Add link</button>
</form>

Mi estado tiene una propiedad de error, si está configurada, mostrará el componente de alerta. Dentro de mi componente de alerta, quiero mostrar el texto de entrega establecido por mi formulario:

const Alert = ({ text, closeCallback }) => (
    <div className="alert">
        {text}
        <button onClick={(e) => closeCallback()}>X</button>
    </div>
);

Desde dentro de mi componente de alerta, quiero poder eliminar el componente de la vista y hacerlo desaparecer del render principal. ¿Pero cómo?

Sé que puedo enviar una función de devolución de llamada desde el padre (que establece el estado de error en una cadena vacía) a mi componente de alerta como:

<Alert closeCallback={parentFunction()} text={this.state.error} />

Pero por cada vez que quiero usar mi componente de alerta en este escenario, tengo que crear esa función de devolución de llamada exacta en mi componente principal junto con mi condición this.state.error && <Alert text={this.state.error} />. ¿Puedo evitar esto de alguna manera?

Soy nueva en Reaccionar por cierto.

0
aventic 19 feb. 2018 a las 21:48

2 respuestas

La mejor respuesta

Puede mantener la función dentro y simplemente devolver null en el render, le dice a React que no renderice nada, así:

import React, { Component } from "react";
import { render } from "react-dom";

class Alert extends Component {
  state = {
    isVisible: true
  };
  handleToggleState = () => {
    this.setState(prevState => ({
      isVisible: !prevState.isVisible
    }));
  };
  render() {
    return this.state.isVisible ? (
      <div className="alert">
        {this.props.text}
        <button onClick={this.handleToggleState}>X</button>
      </div>
    ) : null;
  }
}

class Form extends Component {
  state = { error: "Some weird error" };
  render() {
    return (
      <form onSubmit={this.onSubmit}>
        {this.state.error && <Alert text={this.state.error} />}
        <input
          type="text"
          placeholder="Enter link url"
          value={this.state.url}
          onChange={this.onUrlChange}
        />

        <button type="submit">Add link</button>
      </form>
    );
  }
}

render(<Form />, document.getElementById("root"));
1
Karen Grigoryan 19 feb. 2018 a las 20:29

Simplemente jugueteé con la respuesta de @Karens y se me ocurrió lo siguiente, según el componenteWillReceiveProps, por lo que no tengo que tener la condición en mi vista de formulario, manteniéndolo todo interno para mi componente de alerta:

class Alert extends Component {
  constructor(props) {
    super(props);

    this.state = {
      text: props.text
    };
  }

  componentWillReceiveProps(e) {
    this.setState(e);
  }

  onHide = () => {
    this.setState({ text: '' });
  };

  render() {
    return (
      this.state.text ? (
        <div style={{backgroundColor: 'Red'}}>
          {this.state.text}
          <button onClick={this.onHide}>X</button>
        </div>
      ) : null
    )
  }
}

class Form extends Component {
  constructor() {
    super();
    this.state = {
      error: ''
    };
  }

  onRender = () => {
    this.setState({ error: '123' });
  };

  onHideRender = () => {
    this.setState({ error: '' });
  };

  render() {
    return (
      <div>
        <button onClick={this.onRender}>Render Alert</button>
        <button onClick={this.onHideRender}>Hide Alert</button>
        <Alert text={this.state.error} />
      </div>
    );
  }
}
0
aventic 20 feb. 2018 a las 08:42