I've got an Accordion that has within it a text form (code sandbox: https://codesandbox.io/live/1qr00im):
function MovementAccordion() {
const [formInput, setFormInput] = useState('')
return(
<Accordion>
<Card>
<Accordion.Toggle
as={Card.Header}
eventKey="0">
Accordian Header
</Accordion.Toggle>
<Accordion.Collapse eventKey="0">
<Card.Body>
Fill in the form:
<Form.Control
onChange={(event) => setFormInput(event.target.value)}
type="text"
placeholder="Enter input here" />
<Button
variant="primary"
>
Add
</Button>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
)
}
I've added an onChange() function to the Form so that any time the form is updated it is pushed to state. However, any time the Form is updated the Accordion closes.
If I remove the onChange() function altogether, the form works fine and I can update it at will. The issue comes whenever the onChange() is included.
After spending more time than I'd like to admit trying to find a fix this, I'm stuck.
According to your sandbox:-
you should not call your function
like you call a normal JSX
functional component
. Instead you should've just called it like how normal function
should be called - {PrimaryMovementAccordion()}
if you want to called like the current state you're now. Then that would only be achievable if the SecondaryMovementAccordion
is indeed a JSX
functional component
. So you need to create another React Functional Component
of SecondaryMovementAccordion
, like so, in order to make it work:-
in App.js
:-
import React, { useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import "./styles.css";
import Accordion from "react-bootstrap/Accordion";
import Card from "react-bootstrap/Card";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import SecondaryMovementAccordion from "./SecondaryMovementAccordion";
export default function App() {
const [newPrimary, setNewPrimary] = useState("");
const [newSecondary, setNewSecondary] = useState("");
return (
<>
{/* Incorrect way of calling normal function */}
{/* <PrimaryMovementAccordion /> */}
{/* correct way of calling a normal function */}
{PrimaryMovementAccordion()}
{/* correct way of calling a JSX Functional Component */}
<SecondaryMovementAccordion
newSecondary={newSecondary}
setNewSecondary={setNewSecondary}
/>
<p>Primary: {newPrimary}</p>
<p>Secondary: {newSecondary}</p>
</>
);
// Primary Accordian
function PrimaryMovementAccordion() {
return (
<Accordion defaultActiveKey="0">
<Card>
<Accordion.Toggle as={Card.Header} eventKey="0">
Form accordion
</Accordion.Toggle>
<Accordion.Collapse eventKey="0">
<Card.Body>
Fill in the form:
<Form.Control
type="text"
placeholder="Enter secondary movement"
value={newPrimary}
onChange={(event) => setNewPrimary(event.target.value)}
/>
<p>{newPrimary}</p>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
);
}
}
SecondaryMovementAccordion.js
:-import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import "./styles.css";
import Accordion from "react-bootstrap/Accordion";
import Card from "react-bootstrap/Card";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
const SecondaryMovementAccordion = ({ newSecondary, setNewSecondary }) => {
return (
<Accordion defaultActiveKey="0">
<Card>
<Accordion.Toggle as={Card.Header} eventKey="0">
Form accordion
</Accordion.Toggle>
<Accordion.Collapse eventKey="0">
<Card.Body>
Fill in the form:
<Form.Control
type="text"
placeholder="Enter secondary movement"
value={newSecondary}
onChange={(event) => setNewSecondary(event.target.value)}
/>
<p>{newSecondary}</p>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
);
};
export default SecondaryMovementAccordion;
This is the working sandbox shown above.