skip to Main Content

Form

import { useState, createContext } from "react";
import { data } from "../../../../data";

export const peopleContext = createContext();


export default function Form() {
  const [people, setPeople] = useState(data);
  const [name, setName] = useState("");

  const handleSubmit = (e) => {
    e.preventDefault();
    if (!name) {
      alert("Please Provide Name Value");
      return;
    }
    addPerson();
    setName("");
  };
  const addPerson = () => {
    const fakeId = Date.now();
    const newPerson = { id: fakeId, name };
    setPeople([...people, newPerson]);
  };
  console.log(people)
  return (
    <peopleContext.Provider value={{ people }}>
      <section>
        <form className="form" onSubmit={handleSubmit}>
          <div className="form-row">
            <label htmlFor="name" className="form-label">
              name
            </label>
            <input
              type="text"
              name="name"
              id="name"
              className="form-input"
              value={name}
              onChange={(e) => setName(e.target.value)}
            />
          </div>
          <button className="btn btn-block" type="submit">
            submit
          </button>
        </form>
      </section>
    </peopleContext.Provider>
  );
}

Index

import React, { useContext } from 'react';
import List from './List';
import Form, { peopleContext } from './Form';

const LowerStateChallenge = () => {

 
const l = useContext(peopleContext)
console.log(l)

  return (
    <section>
      <Form />
      {/* <List people={people} /> */}
    </section>
  );
};

export default LowerStateChallenge;

I have created a form Component from which I need to pass people state to LowerStateChallengeComponent, but the context that I have defined in Form is always returning undefined in the parent component.

people state should be passed to the parent component, but the peopleContext is always returning undefined. What did I miss?

2

Answers


  1. As @Nicholas Tower mentioned, you can use lifting-state-up

    e.g.

    App.tsx:

    import { useState } from 'react';
    import Form from './Form';
    import { List } from './List';
    
    export const App = () => {
      const [people, setPeople] = useState([]);
      const [name, setName] = useState('');
    
      const handleSubmit = (e) => {
        e.preventDefault();
        if (!name) {
          alert('Please Provide Name Value');
          return;
        }
        addPerson();
        setName('');
      };
      const addPerson = () => {
        const fakeId = Date.now();
        const newPerson = { id: fakeId, name };
        setPeople([...people, newPerson]);
      };
      console.log(people);
    
      return (
        <div>
          <Form
            onSubmit={handleSubmit}
            onChange={(nextName) => setName(nextName)}
            value={name}
          />
          <List people={people} />
        </div>
      );
    };
    

    Form.tsx:

    import { FormEvent } from 'react';
    
    export type FormProps = {
      onSubmit(e: FormEvent<HTMLFormElement>): void;
      value: string;
      onChange(value: string): void;
    };
    export default function Form({ onSubmit, value, onChange }: FormProps) {
      return (
        <section>
          <form className="form" onSubmit={onSubmit}>
            <div className="form-row">
              <label htmlFor="name" className="form-label">
                name
              </label>
              <input
                type="text"
                name="name"
                id="name"
                className="form-input"
                value={value}
                onChange={(e) => onChange(e.target.value)}
              />
            </div>
            <button className="btn btn-block" type="submit">
              submit
            </button>
          </form>
        </section>
      );
    }
    

    List.tsx:

    import { useLayoutEffect } from 'react';
    import React from 'react';
    
    export const List = ({ people }) => {
      return (
        <ul>
          {people.map((p) => (
            <li key={p.id}>{p.name}</li>
          ))}
        </ul>
      );
    };
    

    stackblitz

    Login or Signup to reply.
  2. I think you have used "Context" in wrong direction from child to parent. Context also work as props from parent to child. so, you should createContext in LowerStateChallenge and useContext in form component.

    for example you can refer :- https://react.dev/reference/react/createContext

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search