Home > Software design >  How to modify or send the state of a child component to the parent (With functional component)
How to modify or send the state of a child component to the parent (With functional component)

Time:04-13

I created my first 2 components in react using functional components, (I didn't understand how to use class based components but that's not the point)

I have logical problems, I do not understand what to do in this situation.

1-) I don't know if I have to send the full state of my child component to the parent either

  1. From the child component modify the state of the parent component

My code has the following structure:

Parent Component:

RequirementCreate (it is a view or page) Contains the following fields:

  • Title of the requirement
  • Description

code:

const RequirementCreate = function () {
  const [requirement_state, setRequirement_state] = useState({
    title: "",
    description: "",
    participants: [],
  });

  return (
    <Content>
      <Box>
        <Title>
          <IconTitle icon="icon" width="30" height="30" />
          Requirement Create
        </Title>
      </Box>
      <BoxContent>
        <InputGroup inputLabel={"Titulo"} iconName={"ic:baseline-abc"} />
        <br />
        <Label>Description</Label>
        <TextArea rows="10" />

        <EmailTag /> <-- CHILD COMPONENT
        <ButtonContainer>
          <Button to="/dashboard/requirement">Add</Button>
        </ButtonContainer>
      </BoxContent>
    </Content>
  );
};
export default RequirementCreate;

Child component:

EmailTag(array of emails)

This component checks If it is a valid email address, if not it is repeated. PS: this component works perfect, 100% code:

const EmailTag = function () {
  const [email_state, setEmail_State] = useState({
    input_value: "",
    emails: ["[email protected]", "[email protected]", "[email protected]"],
    ErrorMessage: "",
  });

  const { emails, input_value, message } = email_state;

  const handleChange = function (e) {
    setEmail_State({ ...email_state, input_value: e.target.value });
  };

  const handleKeyDown = function (e) {
    // logic Handle key Down...
  };

  const handleDelete = function (item) {
// logic handle delete here
  };

  const isInList = function (email) {
    // check if the email address you are trying to enter is already added 
  };

  const isEmail = function (email) {
    // check if it is an email address
  };

  return (
    <>
      <TagContainer>
        <div>
          {emails.map((item, index) => (
            <TagItem key={index}>
              {item}
              <TagButton type="button" onClick={() => handleDelete(item)}>
                <DeleteButton icon="icon1" />
              </TagButton>
            </TagItem>
          ))}
        </div>

        <Input
          placeholder="Participants"
          value={input_value}
          onChange={handleChange}
          onKeyDown={handleKeyDown}
        />
        <span>{ErrorMessage}</span>
      </TagContainer>
    </>
  );
};
export default EmailTag;

CodePudding user response:

In React when this happens you typically want to maintain the state in the parent component, and pass it to the child component as a prop.

You can also pass a function as a prop into your child component and call it from the child.

So something like:

<EmailTag 
  requirement_state={requirement_state} 
  setRequirement_state={setRequirement_state} 
/>

Then in your child component you would have access in your props such as: props.setRequirement_state(...) which would call the function in your parent component.

I would recommend giving this a read.

CodePudding user response:

Parent Component:

 const RequirementCreate = function () {
      const [requirement_state, setRequirement_state] = useState({
        title: "",
        description: "",
        participants: [],
      });

  return (
    <Content>
      <Box>
        <Title>
          <IconTitle icon="icon" width="30" height="30" />
          Requirement Create
        </Title>
      </Box>
      <BoxContent>
        <InputGroup inputLabel={"Titulo"} iconName={"ic:baseline-abc"} />
        <br />
        <Label>Description</Label>
        <TextArea rows="10" />

        <EmailTag 
           requirement_state={requirement_state} 
           setRequirement_state={setRequirement_state} 
       />
        <ButtonContainer>
          <Button to="/dashboard/requirement">Add</Button>
        </ButtonContainer>
      </BoxContent>
    </Content>
  );
};
export default RequirementCreate;

Child Component will look like this and as an example I am modifying the parent state from handleChange method, you can create a separate method as per your needs to modify parent component state:

  const EmailTag = function (props) {
      const [email_state, setEmail_State] = useState({
        input_value: "",
        emails: ["[email protected]", "[email protected]", "[email protected]"],
        ErrorMessage: "",
      });
    
  const { emails, input_value, message } = email_state;

  const handleChange = function (e) {
    setEmail_State({ ...email_state, input_value: e.target.value });
    props.setRequirement_state({    
        title: "Anything as per your needs...",
        description: "Anything as per your needs...",
        participants: ["Anything as per your needs..."]})
     };

  const handleKeyDown = function (e) {
    // logic Handle key Down...
  };

  const handleDelete = function (item) {
// logic handle delete here
  };

  const isInList = function (email) {
    // check if the email address you are trying to enter is already added 
      };
    
      const isEmail = function (email) {
        // check if it is an email address
      };
    
  return (
    <>
      <TagContainer>
        <div>
          {emails.map((item, index) => (
            <TagItem key={index}>
              {item}
              <TagButton type="button" onClick={() => handleDelete(item)}>
                <DeleteButton icon="icon1" />
              </TagButton>
            </TagItem>
          ))}
        </div>

        <Input
          placeholder="Participants"
          value={input_value}
          onChange={handleChange}
          onKeyDown={handleKeyDown}
        />
        <span>{ErrorMessage}</span>
      </TagContainer>
    </>
  );
    };
    export default EmailTag;
  • Related