Estoy tratando de crear constantes en reaccionar de la siguiente manera:
const [firstFocus, setFirstFocus] = React.useState(false); const [lastFocus, setLastFocus] = React.useState(false);Las constantes se utilizan en el código de la siguiente manera:
import React, { Component } from 'react' import axios from 'axios' import { Button, Card, CardHeader, CardBody, CardFooter, Form, Input, InputGroupAddon, InputGroupText, InputGroup, Container, Col } from "reactstrap"; class PostForm extends Component { constructor(props) { super(props) this.state = { email: '', password: '' } } changeHandler = (e) => { this.setState({ [e.target.name]: e.target.value }) } submitHandler = (e) => { e.preventDefault() console.log(this.state) axios.post('https://jsonplaceholder.typicode.com/posts', this.state) .then(response => { console.log(response) }) .catch(error => { console.log(error) }) } render() { const { email, password } = this.state **const [firstFocus, setFirstFocus] = React.useState(false); const [lastFocus, setLastFocus] = React.useState(false);** return ( <div> <Col className="ml-auto mr-auto" md="4"> <Card className="card-login card-plain"> <Form onSubmit={this.submitHandler} className="form"> <CardHeader className="text-center"> </CardHeader> <CardBody> <InputGroup className={ "no-border input-lg" } > <InputGroupAddon addonType="prepend"> <InputGroupText> <i className="now-ui-icons ui-1_email-85"></i> </InputGroupText> </InputGroupAddon> <Input placeholder="Email" type="text" name="email" value={email} onChange={this.changeHandler} // onFocus={() => setFirstFocus(true)} // onBlur={() => setFirstFocus(false)} ></Input> </InputGroup> <InputGroup className={ "no-border input-lg" } > <InputGroupAddon addonType="prepend"> <InputGroupText> <i className="now-ui-icons ui-1_lock-circle-open"></i> </InputGroupText> </InputGroupAddon> <Input placeholder="Password" type="password" name="password" value={password} onChange={this.changeHandler} // onFocus={() => setLastFocus(true)} // onBlur={() => setLastFocus(false)} ></Input> </InputGroup> </CardBody> <CardFooter className="text-center"> <Button block className="btn-round" color="info" type="submit" size="lg" > Get Started </Button> <div className="pull-right"> <h6> <a className="link" href="#pablo" onClick={e => e.preventDefault()} > Need Help? </a> </h6> </div> </CardFooter> </Form> </Card> </Col> </div> ) } } export default PostFormSin embargo, cuando intento hacer esto me sale el siguiente error:
Llamada de gancho no válida. Los ganchos solo se pueden llamar dentro del cuerpo de un componente de función.
Creé otra constante allí para el correo electrónico y la contraseña y funcionó bien, así que no estoy seguro de por qué mis constantes useState no funcionan. Cualquier ayuda u orientación es muy apreciada ya que soy muy nuevo para reaccionar. ¡Gracias!
Está intentando usar useState, que es un gancho de React, dentro de un componente de clase. Esto no funcionará. Los ganchos solo se pueden utilizar en componentes funcionales.
En reaccionar, tenemos 2 formas de construir componentes: clases y funciones.
Los ganchos son una nueva incorporación en React 16.8. Le permiten usar el estado y otras características de React sin escribir una clase.
Usando el gancho de estado:
import React, { useState } from 'react'; function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }Ejemplo de clase equivalente:
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } }Oficialmente, no puede usar el gancho en el componente de clase. Pero, por supuesto, hay algún truco si quieres usar useState en el componente de clase
ejemplo, no puedes hacer esto
class Example extends React.Component { _renderCounter = () => { // // YOU CAN'T DO THIS // REACT WONT ALLOW YOU // const [count, setCount] = useState(0); return <div>{ count }</div> } render() { return( <div>{ this._renderCounter() }</div> ); } }Pero, con un pequeño truco puedes hacer esto. React te permitirá
class Example extends React.Component { _renderCounter = () => () => { const [count, setCount] = useState(0); return <div>{ count }</div> } render() { const MyInlineHook = this._renderCounter(); return( <div><MyInlineHook /></div> ); } } Con este truco, puede acceder a this y a los props del componente de clase. :)
Otra forma es usar ganchos en un componente funcional y luego importar este componente funcional en un componente de clase.
export default class LikeButton extends Component { render() { return <Like />; } } function Like() { const [like, setLike] = useState(100); const [liked, toggleLike] = useState(false); const handleLike = () => { if (liked == false) { setLike(like + 1); toggleLike(true); } else { setLike(like - 1); toggleLike(false); } }; return ( <> <div> <h2>Like Button</h2> <button onClick={() => handleLike()} className={`like-button ${liked == true ? "liked" : ""}`} > Like | <span className="likes-counter">{like}</span> </button> </div> </> ); }Esto funcionó para mí, acabo de declarar index & setIndex de la siguiente manera. Puede ser un truco sucio, pero oye 🤷♂️
render(){ const index = this.state.index; const setIndex = (params) => this.setState({index: params}); return { <Tab value={index} onChange={setIndex}> <Tab.Item title="recent" /> <Tab.Item title="favorite" /> <Tab.Item title="cart" /> </Tab> <TabView value={index} onChange={setIndex} > <TabView.Item style={{ backgroundColor: 'red', width: '100%' }}> <Text h1>recent</Text> </TabView.Item> <TabView.Item style={{ backgroundColor: 'blue', width: '100%' }}> <Text h1>Favorite</Text> </TabView.Item> <TabView.Item style={{ backgroundColor: 'green', width: '100%' }}> <Text h1>Cart</Text> </TabView.Item> </TabView> } }