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
- 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;