Я пытаюсь получить данные из моих полей ввода на компоненте самого низкого уровня - PullRequest
0 голосов
/ 07 октября 2019

У меня есть состояние , расположенное в моем компоненте уровня APP, и я пытаюсь захватить данные, помещаемые в мой компонент формы. Я использую крючки, но я не могу понять, что я делаю неправильно!

Я попытался перевести состояние на уровень формы, но оно возвращает неопределенное значение, моя конечная цель - отправить эти данные в firebase и отобразить их в таблице на другой странице моего приложения.

APP

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

import Header from "./components/Header";
import About from "./components/About";

const App = () => {
  const [date, setDate] = useState("");
  const [name, setName] = useState("");
  const [hours, setHours] = useState("");
  const [description, setDescription] = useState("");

  return (
    <div>
      <Header />
    </div>
  );
};

render(<App />, document.getElementById("root"));

** Компонент HEADER / ROUTER

import React from "react";
import { render } from "react-dom";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  NavLink,
  Link
} from "react-router-dom";

import Home from "./pages/home/Home";
import Data from "./pages/data/Data";
import About from "./pages/about/About";
import Contact from "./pages/contact/Contact";


import "../style.css";

const Header = () => {
  return (
    <Router>
      <div>
        <nav className="navbar">
          <NavLink className="link nav-item" to="/entry">
            Time Entry
          </NavLink>
          <NavLink className="link nav-item" to="/data">
            Data
          </NavLink>
          <NavLink className="link nav-item-right" to="/about">
            About
          </NavLink>
          <NavLink className="link nav-item-right" to="/contact">
            Contact
          </NavLink>
        </nav>

        {/* A <Switch> looks through its children <Route>s and
            renders the first one that matches the current URL. */}
        <Switch>
          <Route exact path="/entry" component={Home} />
          <Route exact path="/data" component={Data} />
          <Route exact path="/about" component={About} />
          <Route exact path="/contact" component={Contact} />
        </Switch>
      </div>
    </Router>
  );
};

export default Header;

HOME Компонент страницы

import React, { Fragment } from "react";

import InputForm from "./Form";

const Home = props => {
  return (
    <Fragment>
      <InputForm />
    </Fragment>
  );
};

export default Home;

ФОРМАЛЬНЫЙ компонент

import React, { Fragment, useState, createRef } from "react";
import { Button, Form, FormGroup, Label, Input, FormText } from "reactstrap";

const InputForm = props => {


  const dateEntry = createRef();
  const nameEntry = createRef();
  const hourEntry = createRef();
  const descriptionEntry = createRef();

  const handleClick = e => {
    e.preventDefault();
    setDate(dateEntry.current.value);
    setName(nameEntry.current.value);
    setHours(hourEntry.current.value);
    setDescription(descriptionEntry.current.value);
    // console.log(nameEntry.current.value);
  };

  return (
    <Form className="data-entry">
      <FormGroup className="form-entry-items">
        <Label className="label">Date</Label>
        <Input type="date" className="input" ref={dateEntry} />
      </FormGroup>
      <FormGroup className="form-entry-items">
        <Label className="label">Lease Acconting Manager Name</Label>{" "}
        <Input type="text" className="input" ref={nameEntry} />
      </FormGroup>
      <FormGroup className="form-entry-items">
        <Label className="label">Hours Worked</Label>{" "}
        <Input className="input" ref={hourEntry}/>
      </FormGroup>
      <FormGroup className="form-entry-items">
        <Label className="label">Description</Label>{" "}
        <Input type="textarea" className="input" ref={descriptionEntry}/>
      </FormGroup>
      <Button onClick={handleClick}>Submit</Button>
    </Form>
  );
};

export default InputForm;

Ответы [ 2 ]

1 голос
/ 07 октября 2019

Лучше всего пойти с react redux, но в случае, если вы не хотите, вы должны создать функцию уровня приложения и настроить ее через всех дочерних элементов до компонента InputForm, где вы будете использовать обратный вызов onchage. в Input чтобы передать событие обратно родителю. в зависимости от реализации функции в родительском компоненте App вы установите значение в состояние, значение правильности должно быть примерно таким:

const App = () => {
  const [date, setDate] = useState("");
  const [name, setName] = useState("");
  const [hours, setHours] = useState("");
  const [description, setDescription] = useState("");
 handleChange = (e) => {
  //logic to set the specific value to state
  // you can use e.target.value as well as e.target.name to capture the value and decice which state variable to update. eg.
  if(e.target.name =="name") setName(e.target.value)
//do same for all the other state variables
 }
  return (
    <div>
      <Header handleChange={handleChange } />
    </div>
  );
};

render(<App />, document.getElementById("root"));

Тогда внутри компонента Header у вас это будет выглядеть следующим образом

const Header = (props) => {
  return (
    <Router>
      <div>
        <nav className="navbar">
          <NavLink className="link nav-item" to="/entry">
            Time Entry
          </NavLink>
          <NavLink className="link nav-item" to="/data">
            Data
          </NavLink>
          <NavLink className="link nav-item-right" to="/about">
            About
          </NavLink>
          <NavLink className="link nav-item-right" to="/contact">
            Contact
          </NavLink>
        </nav>

        {/* A <Switch> looks through its children <Route>s and
            renders the first one that matches the current URL. */}
        <Switch>
          <Route exact path="/entry" render={(props) => <Home {...props} />}  />
          <Route exact path="/data" component={Data} />
          <Route exact path="/about" component={About} />
          <Route exact path="/contact" component={Contact} />
        </Switch>
      </div>
    </Router>
  );
};

export default Header;

Тогда домашний компонент будет выглядеть следующим образом

import React, { Fragment } from "react";

import InputForm from "./Form";

const Home = props => {
  return (
    <Fragment>
      <InputForm handleChange={props.handleChange} />
    </Fragment>
  );
};

export default Home; 

На уровне формы теперь вы можете сделать следующее

import React, { Fragment, useState, createRef } from "react";
import { Button, Form, FormGroup, Label, Input, FormText } from "reactstrap";

const InputForm = props => {
//using the handleChange function propergated from the parent component we will send the event and use it at the parent to collect the name and value artribute of the input. 

  return (
    <Form className="data-entry">
      <FormGroup className="form-entry-items">
        <Label className="label">Date</Label>
        <Input type="date" className="input" onChange={(e)=>props.handleChange(e)}/>
      </FormGroup>
      <FormGroup className="form-entry-items">
        <Label className="label">Lease Acconting Manager Name</Label>{" "}
        <Input name="name"  onChange={(e)=>props.handleChange(e)} type="text" className="input"  />
      </FormGroup>
      <FormGroup className="form-entry-items">
        <Label className="label">Hours Worked</Label>{" "}
        <Input name="hours" className="input" onChange={(e)=>props.handleChange(e)}/>
      </FormGroup>
      <FormGroup className="form-entry-items">
        <Label className="label">Description</Label>{" "}
        <Input type="textarea" name="description" className="input" onChange={(e)=>props.handleChange(e)}/>
      </FormGroup>
      <Button >Submit</Button>
    </Form>
  );
};

export default InputForm;
1 голос
/ 07 октября 2019

Во-первых, вы должны спросить, почему вы устанавливаете состояние APP со значениями, которые будут использоваться только InputForm . Если вы просто собираетесь использовать их в InputForm , вам следует переместить ваше состояние в этот компонент.

Возможно, просто установите state внутри InputForm вместо iofиспользуйте createRef, чтобы вы могли обрабатывать их там без propdrilling или чего-либо еще.

import React, { Fragment, useState, createRef } from "react";
import { Button, Form, FormGroup, Label, Input, FormText } from "reactstrap";

const InputForm = props => {

  const [date, setDate] = useState("");
  const [name, setName] = useState("");
  const [hours, setHours] = useState("");
  const [description, setDescription] = useState("");

  /* Im not sure How this works inside your component Input, but why dont just use a onChange?*/
  const dateEntry = createRef();
  const nameEntry = createRef();
  const hourEntry = createRef();
  const descriptionEntry = createRef();

  const handleInput = ( e, type)  => {
    switch( type ){
     case'name':
       setName( e.target.value );
     break;
     case'date':
       setDate( e.target.value );
     break;
    case'description':
       setDescription( e.target.value );
     break;
     case'hours':
       setHours( e.target.value );
     break;
    }
  }

  const handleClick = e => {
    e.preventDefault();
    //Just submit your data or something...  
  };

  return (
    <Form className="data-entry">
      <FormGroup className="form-entry-items">
        <Label className="label">Date</Label>
        <Input type="date" className="input" ref={dateEntry} onChange={ e => {handleChange( e, 'date') } } />
      </FormGroup>
      <FormGroup className="form-entry-items">
        <Label className="label">Lease Acconting Manager Name</Label>{" "}
        <Input type="text" className="input" ref={nameEntry} onChange={ e => {handleChange( e, 'name' ) } } />
      </FormGroup>
      <FormGroup className="form-entry-items">
        <Label className="label">Hours Worked</Label>{" "}
        <Input className="input" ref={hourEntry} onChange={ e => {handleChange( e, 'hours') } }/>
      </FormGroup>
      <FormGroup className="form-entry-items">
        <Label className="label">Description</Label>{" "}
        <Input type="textarea" className="input" ref={descriptionEntry} onChange={ e => {handleChange( e, 'description') } }/>
      </FormGroup>
      <Button onClick={handleClick}>Submit</Button>
    </Form>
  );
};

export default InputForm;

Если вам нужен доступ к значениям Form из любого другого компонента, попробуйте реализовать то же самоес контекстом , и, возможно, попробуйте добавить им некоторые действия и редукторы .

Проверьте это, если вам нужна дополнительная информация: Документы контекста , Документы редуктора

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...