How can I access props from inside a component - javascript

I'm trying to access "props" from a component for which I'm passing an object. I'm a bit lost with JS here ; basically what I'm trying to do is to build a Master/Detail view (so show/hide 2 different components based on user clicks on a table).
How can I access "props" from the object rowEvent once a user clicks on a table row ?
const rowEvents = {
onClick: (e, row, rowIndex) => {
console.log(row.itemId);
//this.currentItemId= row.itemId; //////////// THIS DOESNT WORK...
}
};
const TableWithSearch = (props) => {
const { SearchBar } = Search;
const { ExportCSVButton } = CSVExport;
return (
<Card>
<CardBody>
<h4 className="header-title">Search and Export</h4>
<p className="text-muted font-14 mb-4">A Table</p>
<ToolkitProvider
bootstrap4
keyField="itemId"
data={props.data}
columns={columns}
search
exportCSV={{ onlyExportFiltered: true, exportAll: false }}>
{props => (
<React.Fragment>
<Row>
<Col>
<SearchBar {...props.searchProps} />
</Col>
<Col className="text-right">
<ExportCSVButton {...props.csvProps} className="btn btn-primary">
Export CSV
</ExportCSVButton>
</Col>
</Row>
<BootstrapTable
{...props.baseProps}
bordered={false}
rowEvents={ rowEvents }
defaultSorted={defaultSorted}
pagination={paginationFactory({ sizePerPage: 5 })}
wrapperClasses="table-responsive"
/>
</React.Fragment>
)}
</ToolkitProvider>
</CardBody>
</Card>
);
};
And the component looks like this :
render() {
let show;
if (this.props.currentItemId === null){
show = (<TableWithSearch data={this.props.data} />)
}
else {
show = (<DisplayItem />)
}
return (
<React.Fragment>
<Row>
<Col>
{ show }
</Col>
</Row>
</React.Fragment>
)
}
}

Your issue is a bit complex because you seem to be needing to update the prop currentItemId from parent's parent.
You can solve your issue by doing the following:
Move the declaration of rowEvents objects in side TableWithSearch functional component.
In TableWithSearch component, receive a callback say updateCurrentItemId from parent which updates the currentItemId in the parent
In parent component, the currentItemId is being passed from parent(again). So maintain a state for it.
TableWithSearch Component
const TableWithSearch = (props) => {
const { SearchBar } = Search;
const { ExportCSVButton } = CSVExport;
const {updateCurrentItemId} = props; //<--------- receive the prop callback from parent
const rowEvents = {
onClick: (e, row, rowIndex) => {
console.log(row.itemId);
updateCurrentItemId(row.itemId) // <--------- use a callback which updates the currentItemId in the parent
//this.currentItemId= row.itemId; //////////// THIS DOESNT WORK...
},
};
return (
<Card>
<CardBody>
<h4 className="header-title">Search and Export</h4>
<p className="text-muted font-14 mb-4">A Table</p>
<ToolkitProvider
bootstrap4
keyField="itemId"
data={props.data}
columns={columns}
search
exportCSV={{ onlyExportFiltered: true, exportAll: false }}
>
{(props) => (
<React.Fragment>
<Row>
<Col>
<SearchBar {...props.searchProps} />
</Col>
<Col className="text-right">
<ExportCSVButton
{...props.csvProps}
className="btn btn-primary"
>
Export CSV
</ExportCSVButton>
</Col>
</Row>
<BootstrapTable
{...props.baseProps}
bordered={false}
rowEvents={rowEvents}
defaultSorted={defaultSorted}
pagination={paginationFactory({ sizePerPage: 5 })}
wrapperClasses="table-responsive"
/>
</React.Fragment>
)}
</ToolkitProvider>
</CardBody>
</Card>
);
};
Parent Component
class ParentComp extends React.Component {
state = {
curItemId: this.props.currentItemId
}
updateCurrentItemId = (udpatedCurId) => {
this.setState({
curItemId: udpatedCurId
})
}
render() {
let show;
// if (this.props.currentItemId === null){
if (this.state.curItemId === null){
show = (<TableWithSearch data={this.props.data} updateCurrentItemId={this.updateCurrentItemId}/>)
}
else {
show = (<DisplayItem />)
}
return (
<React.Fragment>
<Row>
<Col>
{ show }
</Col>
</Row>
</React.Fragment>
)
}
}
}

this.props should give you access for class components
In addition you should create a bind to the click function so it can correctly resolve this, in the constuctor of the rowEvent

Related

How to correctly fill the grid antd with data from the server

I made such a grid using grid antd . code here.
const { Row, Col } = antd;
const App = () => (
<Row>
<Col className={'first'} span={16}>
<img src="https://picsum.photos/800/400?random=1"/>
</Col>
<Col span={8}>
<Row>
<Col className={'second'} span={24}>
<img src="https://picsum.photos/800/400?random=2"/>
</Col>
<Col className={'third'} span={24}>
<img src="https://picsum.photos/800/400?random=3"/>
</Col>
</Row>
</Col>
</Row>
)
const ComponentDemo = App;
ReactDOM.render(<ComponentDemo />, mountNode);
I'm getting data from the server. There may be more than 3 of them there. I should output the first 3 like this. The rest will be displayed after pressing the button. How can this effect be achieved in myData.map(). To output these elements without using indexes?
I will try do somthing like this
dataSale.slice(0,maxCount).map(({...item},index)=>(
(index===0)?(
<Col key = {index} span={16}>
<SaleCard {...item}/>
</Col>
):(
<Col key={index} span={8}>
<SaleCard {...item}/>
</Col>
)
))
I hope this helps. The following code should work with any number of image links sent by the server. I have mocked with 9 images.
I followed components approach, like what you are supposed to when working with React. I created some components and pieced them back-together to create the design that you wanted to with map().
const { Row, Col, Button } = antd;
const {useState} = React;
const data = [
"https://picsum.photos/800/400?random=1",
"https://picsum.photos/800/400?random=2",
"https://picsum.photos/800/400?random=3",
"https://picsum.photos/800/400?random=4",
"https://picsum.photos/800/400?random=5",
"https://picsum.photos/800/400?random=6",
"https://picsum.photos/800/400?random=7",
"https://picsum.photos/800/400?random=8",
"https://picsum.photos/800/400?random=9",
]
const ColWithImage = (props) => (
<Col span={props.n % 3 == 1 ? 16 : 24}>
<img src={data[props.n-1]}/>
</Col>
)
const MainRow = (props) => {
const k = props.n*3 + 1;
return (
<Row>
<ColWithImage n={k}/>
<Col span={8}>
<Row>
<ColWithImage n={k+1}/>
<ColWithImage n={k+2}/>
</Row>
</Col>
</Row>
)}
const Container = (props) => {
// Create an iterable array depending upon the number of image links
const arr = Array.from(Array(Math.floor(data.length/3)))
// Show only one row if the button is not clicked
// But show all the rows if the button is clicked
return !props.buttonClicked
? <><MainRow n={0}/></>
: (<>
{
arr.map((item, index) => <MainRow key={index} n={index}/>)
}
</>)
}
const App = () => {
const [buttonClicked, setButtonClicked] = useState(false);
const [buttonText, setButtonText ] = useState("Show More");
const handleClick = () => {
setButtonClicked(!buttonClicked);
setButtonText(buttonClicked ? "Show More" : "Show Less");
}
return (<>
<Container buttonClicked={buttonClicked}/>
<Button onClick={handleClick}>{buttonText}</Button>
</>)
}
const ComponentDemo = App;
ReactDOM.render(<ComponentDemo />, mountNode);
You can view the result here.
I created a SalesView component and it will render the layout as per you requirement. It receives an items array of length less than or equal to 3 (Suppose you have total 5 records, only two records will be displayed in second row).
Hope this solution solves your problem.
import { useState } from "react";
import { Row, Col, Button } from "antd";
import "antd/dist/antd.min.css";
const list = Array.from({ length: 20 }).map((_, i) => ({
id: i,
url: `https://picsum.photos/800/400?random=${i + 1}`,
}));
const SalesCard = ({ id, url }) => {
return <img src={url} />;
};
const SalesView = ({ items }) => {
return (
<Row>
{items?.[0] && (
<Col span={16}>
<SalesCard {...items[0]} />
</Col>
)}
{items.length > 2 && (
<Col span={8}>
<Row>
{items?.[1] && (
<Col span={24}>
<SalesCard {...items[1]} />
</Col>
)}
{items?.[2] && (
<Col span={24}>
<SalesCard {...items[2]} />
</Col>
)}
</Row>
</Col>
)}
</Row>
);
};
function App() {
const [showAll, setShowAll] = useState(false);
const totalChunks = Math.ceil(list.length / 3);
const data = Array.from({ length: showAll ? totalChunks : 1 }).map((_, index) => {
const startIndex = index * 3;
const endIndex = startIndex + 3;
return <SalesView key={index} items={list.slice(startIndex, endIndex)} />;
});
const onClick = () => setShowAll(true);
return (
<>
{data}
{!showAll && <Button onClick={onClick}>Show More</Button>}
</>
);
}
export default App;
you can achieve it via CSS or use ternary
dataSale.map((item, index) =>
<Col key={index} span={index < 3 ? 16 : 8}>
<SaleCard {...item}/>
</Col>
)

React Class Component is not changing with the change of its props [duplicate]

react-router-dom v5 and React 16
My loading app component contains:
ReactDOM.render(
<FirebaseContext.Provider value={new Firebase()}>
<BrowserRouter>
<StartApp />
</BrowserRouter>,
</FirebaseContext.Provider>,
document.getElementById("root")
);
I have a route component which contains:
{
path: "/member/:memberId",
component: MemberForm,
layout: "/admin"
},
Admin component:
return (
<>
<div className="main-content" ref="mainContent">
<LoadingComponent loading={this.props.authState.loading}>
<AdminNavbar
{...this.props}
brandText={this.getBrandText(this.props.location.pathname)}
/>
<AuthDetailsProvider>
<Switch>{this.getRoutes(routes)}</Switch>
</AuthDetailsProvider>
<Container fluid>
<AdminFooter />
</Container>
</LoadingComponent>
</div>
</>
)
this.getRoutes in the Switch contains the reference route above.
Now from one of my component pages I can navigate to /member/{memberid} this works fine.
the route loads a component called MemberForm
inside MemberForm I have a row that contains this method:
<Row>
{ this.displayHouseholdMembers() }
</Row>
displayHouseholdMembers = () => {
const householdDetails = this.state.family;
if (householdDetails) {
return householdDetails.map((key, ind) => {
if (key['uid'] != this.state.memberKeyID) {
return (
<Row key={ind} style={{ paddingLeft: '25px', width: '50%'}}>
<Col xs="5">
<Link to={ key['uid'] }>
{ key['first'] + " " + key['last'] }
</Link>
</Col>
<Col xs="4">
{ key['relation'] }
</Col>
<Col xs="3">
<Button
color="primary"
size="sm"
onClick={(e) => this.removeHouseRelation(key)}
>
Remove
</Button>
</Col>
</Row>
);
}
});
}
};
MemberForm:
in componentDidMount I do an firebase call to check for the data pertaining to the user using the uid aka memberId in the URL.
class MemberForm extends React.Component {
constructor(props) {
super(props);
this.state = {
...INITIAL_STATE,
currentOrganization: this.props.orgID,
householdRelation: ['Spouse', 'Child', 'Parent', 'Sibling'],
householdSelected: false,
};
}
componentDidMount() {
let urlPath, personId;
urlPath = "members";
personId = this.props.match.params.memberId;
// if it is a member set to active
this.setState({ statusSelected: "Active" })
this.setState({ memberSaved: true, indiUid: personId });
// this sets visitor date for db
const setVisitorDate = this.readableHumanDate(new Date());
this.setState({ formType: urlPath, visitorDate: setVisitorDate }, () => {
if (personId) {
this.setState({ memberSaved: true, indiUid: personId });
this.getIndividualMemberInDB(
this.state.currentOrganization,
personId,
this.state.formType,
INITIAL_STATE
);
}
});
}
...
return (
<>
<UserHeader first={s.first} last={s.last} />
{/* Page content */}
<Container className="mt--7" fluid>
<Row>
...
<Row>
{ this.displayHouseholdMembers() }
</Row>
</Form>
</CardBody>
) : null}
</Card>
</Col>
</Row>
<Row>
<Col lg="12" style={{ padding: "20px" }}>
<Button
color="primary"
onClick={e => this.submitMember(e)}
size="md"
>
Save Profile
</Button>
{ this.state.indiUid ? (
<Button
color="secondary"
onClick={e => this.disableProfile()}
size="md"
>
Disable Profile
</Button>
) : null }
</Col>
</Row>
</Container>
</>
);
When I click on the Link it shows the url has changed 'members/{new UID appears here}' but the page does not reload. I believe what's going on is that since it's using the same route in essence: path: "/member/:memberId"it doesn't reload the page. How can I get it to go to the same route but with the different memberId?
You are correct that the MemberForm component remains mounted by the router/route when only the path param is updating. Because of this the MailForm component needs to handle prop values changing and re-run any logic depending on the prop value. The componentDidUpdate is the lifecycle method to be used for this.
Abstract the logic into a utility function that can be called from both componentDidMount and componentDidUpdate.
Example:
getData = () => {
const urlPath = "members";
const { memberId } = this.props.match.params;
// this sets visitor date for db
const setVisitorDate = this.readableHumanDate(new Date());
this.setState(
{
// if it is a member set to active
statusSelected: "Active",
memberSaved: true,
indiUid: memberId,
formType: urlPath,
visitorDate: setVisitorDate
},
() => {
if (memberId) {
this.setState({ memberSaved: true, indiUid: memberId });
this.getIndividualMemberInDB(
this.state.currentOrganization,
memberId,
this.state.formType,
INITIAL_STATE
);
}
}
);
}
The lifecycle methods:
componentDidMount() {
this.getData();
}
componentDidUpdate(prevProps) {
if (prevProps.match.params.memberId !== this.props.match.params.memberId) {
this.getData();
}
}
For react-router-dom v6, can you try with simple routing? Create a Test.js with
const Test = ()=> <h1>Test Page</h1>
Then, create a Home.js with
const Home = ()=> <Link to="/test">Test</Link>
Then, add them to route.
<BrowserRouter>
<Routes>
<Route path="/" element={<Home/>} />
<Route path="/test" element={<Test />} />
</Routes>
</BrowserRouter>
Does your component structure look like this? For index route, look more at https://reactrouter.com/docs/en/v6/getting-started/overview.

Show one div and hide another in an array with onMouseEnter in React

I have an array of items that i want to show with a map function, and every item is shown as a card.
I'm trying to show two kinds of cards with a different content, one if "isHover" is false, and the other if it true using onMouseEnter/onMouseOver.
I made "isHover" as an array in order to know which item to show/hide.
(The "isHover" array has the same length that the items' array has).
The problem is that when I hover one card it dissappears and nothing is shown in place of it. :(
The code:
function TeachersShow(props) {
const [isHover, setIsHover] = useState(null);
const updateIsHover = (index, isHover1) => {
let newArray = isHover;
newArray[index] = isHover1;
setIsHover([...newArray]);
console.log(isHover[index]);
};
return (
<div>
{isHover[index] === false && (<Card className="teacher-card"
onMouseEnter={() => { updateIsHover(index, true) }}
key={index}
item={item}
onClick={() => navigateToTeacher(item)}
>
<Card.Img className="teachersImg" src={item.photoURL}>
</Card.Img>
<Card.Title className=" teachersName">
{item.username}
</Card.Title>
</Card>)}
{isHover[index] === true && (
<Card className="card-hover"
onMouseleave={() => { updateIsHover(index, false) }}
key={index}
item={item}
onClick={() => navigateToTeacher(item)}
>
<Card.Title className=" teachersName">
{item.username}
</Card.Title>
<Card.Subtitle className="proTeacher">
{`${item.profession} teacher`}
</Card.Subtitle>
<Card.Text className="teacherDesc">
{item.teacher_description}
</Card.Text>
</Card>)}
</Col>
))}
<Col></Col>
</Row>
</div>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(TeachersShow);
It's little hard to tell what's wrong, since a lot of information is missing from the code. But try to create a component Let's say <Teacher />, and let it be responsible for hovering action. Try this:
function Teacher(item) {
const [hover, setHover] = useState(false);
const renderCardData = () => {
if (!hover) {
return (
<Card.Img className="teachersImg" src={item.photoURL} />
<Card.Title className="teachersName">
{item.username}
</Card.Title>
);
}
return (
<Card.Title className=" teachersName">
{ item.username }
</Card.Title>
<Card.Subtitle className="proTeacher">
{ `${item.profession} teacher` }
</Card.Subtitle>
<Card.Text className="teacherDesc">
{ item.teacher_description }
</Card.Text>
);
};
return (
<Card
className={ hover
? 'card-hover'
: 'teacher-card' }
onMouseEnter={ () => setHover(true) }
onMouseLeave={ () => setHover(false) }
>
{ renderCardData() }
</Card>
);
}
export default Teacher;
And you render it like that:
function TeachersList(teachers) {
return teachers.map(Teacher);
};

passing function in React Js

I need to pass bookLeacture function from AvailableCourses into LectureItem (inside Button onClick). But I think I can define only variable inside LectureItem but could not define as a function. Can you explain how can I call and define it?
const LectureItem = props => {
let l = props.lecture;
// let bookLeacture=props.bookLeacture
return (
<>
<Container>
<Row>
<Col>
<Alert variant="primary">
<Row>
{l.booked === false && (
<Col>
<Button
onClick={this.bookLeacture(l.lectureId)}
variant="success"
block
>
Book Now
</Button>
</Col>
)}
</Row>
</Alert>
</Col>
</Row>
</Container>
</>
);
};
class AvailableCourses extends React.Component {
bookLeacture = id => {
API.bookLeacture(id)
.then(res => {
console.log(res);
this.setState({ lectures: res, loading: null, serverErr: null });
})
.catch(err => {
this.setState({ serverErr: true, loading: null });
});
};
constructor(props) {
super(props);
this.state = { lectures: [] };
}
render() {
return (
<>
<Container fluid>
<Row className="justify-content-md-center below-nav">
<h3>Available Courses: </h3>
</Row>
{this.state.lectures.map(e => {
return <LectureItem lecture={e} bookLeacture={this.bookLeacture} />;
})}
</Container>
</>
);
}
}
export default AvailableCourses;
You've got a Functional Component there, which doesn't have classful arguments. This means, this is not valid here. So all you need to do is, change the following:
onClick={this.bookLeacture(l.lectureId)}
to this, plus the above is not a right way too, it gets executed immediately:
onClick={() => bookLeacture(l.lectureId)}
Also, you don't need fragments <></> for returning the Container.
Ultimately I'd do something like this:
const LectureItem = ({ lecture, bookLeacture }) => {
return (
<Container>
<Row>
<Col>
<Alert variant="primary">
<Row>
{lecture.booked === false && (
<Col>
<Button
onClick={() => bookLeacture(lecture.lectureId)}
variant="success"
block
>
Book Now
</Button>
</Col>
)}
</Row>
</Alert>
</Col>
</Row>
</Container>
);
};
class AvailableCourses extends React.Component {
state = { lectures: [] };
bookLeacture = id => {
API.bookLeacture(id)
.then(res => {
console.log(res);
this.setState({ lectures: res, loading: null, serverErr: null });
})
.catch(err => {
this.setState({ serverErr: true, loading: null });
});
};
render() {
return (
<Container fluid>
<Row className="justify-content-md-center below-nav">
<h3>Available Courses:</h3>
</Row>
{this.state.lectures.map(e => {
return <LectureItem lecture={e} bookLeacture={this.bookLeacture} />;
})}
</Container>
);
}
}
export default AvailableCourses;
I would do some more things additionally:
Make the alert look neater using MyAlert component.
Add a key prop so that it works fine.
Remove unnecessary fragments <></>.
Remove the old constructor concept and add state.
Full optimised source:
const MyAlert = ({ children }) => (
<Container>
<Row>
<Col>
<Alert variant="primary">
<Row>{children}</Row>
</Alert>
</Col>
</Row>
</Container>
);
const LectureItem = ({ lecture, bookLeacture }) => {
return (
<MyAlert>
{lecture.booked === false && (
<Col>
<Button
onClick={() => bookLeacture(lecture.lectureId)}
variant="success"
block
>
Book Now
</Button>
</Col>
)}
</MyAlert>
);
};
class AvailableCourses extends React.Component {
state = { lectures: [] };
bookLeacture = id => {
API.bookLeacture(id)
.then(res => {
console.log(res);
this.setState({ lectures: res, loading: null, serverErr: null });
})
.catch(err => {
this.setState({ serverErr: true, loading: null });
});
};
render() {
return (
<Container fluid>
<Row className="justify-content-md-center below-nav">
<h3>Available Courses:</h3>
</Row>
{this.state.lectures.map((e, key) => {
return (
<LectureItem
lecture={e}
bookLeacture={this.bookLeacture}
key={key}
/>
);
})}
</Container>
);
}
}
export default AvailableCourses;
You are on track already.
You would have to do something like this on the button.
But I think you want "id" of the item passed as well, so do something like this.
<button onClick={()=>props.bookLeacture(props.lecture.id)}/>

Passing props to children in React

I'm trying to make a Formik wrapper which takes children as props and would render anything put inside. There are a couple forms to make which take different initial values and validation schema etc. The only thing in common thing is the grid layout. The goal is to have the access to Formik props like values, errors etc. in the child component and I have no idea how to pass it to its child. The form fields don't even show up.
The wrapper:
import React from 'react';
import { Formik, FormikConfig, FormikValues } from "formik";
import { Col, Layout, Row } from "antd";
const FormContainer: React.FC<FormikConfig<FormikValues>> = ({ children, ...props }) => {
return <Formik
{...props}
>
{props => (
<Layout>
<Row style={{ height: "100vh", display: "flex", alignItems: "center" }}>
<Col span={12}>
<Layout>
{/*this will be replaced with some background image*/}
<pre>{JSON.stringify(props.values, null, 2)}</pre>
<pre>{JSON.stringify(props.errors, null, 2)}</pre>
</Layout>
</Col>
<Col span={12}>
<Layout>
{/*here goes goes a Form from a different components*/}
{children}
</Layout>
</Col>
</Row>
</Layout>
)}
</Formik>
};
export default FormContainer;
I must be doing something wrong. I am unable to get any Formik props/values from anywhere else when I wrap FormContainer around anything.
My form example (so far):
import React from "react";
import { Field, Form } from "formik";
import { Col, Form as AntForm, Icon, Input, Row } from "antd";
import { initialValues, validationSchema } from "./fieldValidation";
import FormContainer from "../../../containers/FormContainer/FormContainer";
const RegisterPage: React.FC = () => {
return (
<FormContainer
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={(data, { setSubmitting }) => {
setSubmitting(true);
setTimeout(() => {
alert(JSON.stringify(data, null, 2));
setSubmitting(false);
}, 5000);
}}
>
{({touched, errors}) => (
<Form>
<Row gutter={[8, 8]}>
<Col span={12}>
<AntForm.Item
help={touched.firstName && errors.firstName ? errors.firstName : ""}
validateStatus={touched.firstName && errors.firstName ? "error" : undefined}
>
<Field
name="firstName"
prefix={<Icon type="solution" style={{ color: "rgba(0,0,0,.25)" }} />}
placeholder="First name"
as={Input}
/>
</AntForm.Item>
</Col>
<Col span={12}>
<AntForm.Item
help={touched.lastName && errors.lastName ? errors.lastName : ""}
validateStatus={touched.lastName && errors.lastName ? "error" : undefined}
>
<Field
name="lastName"
prefix={<Icon type="solution" style={{ color: "rgba(0,0,0,.25)" }} />}
placeholder="Last name"
as={Input}
/>
</AntForm.Item>
</Col>
</Row>
</Form>
)}
</FormContainer>
);
};
export default RegisterPage;
I'm stuck. What am I doing wrong here?
Here's how to pass the prop "propsToPass" from the parent to all his direct children:
const Parent = props => {
const { children } = props;
const childrenWithExtraProp = React.Children.map(children, child =>
React.cloneElement(child, { propsToPass: "toChildren" })
);
return <div>{childrenWithExtraProp}</div>;
};
export default Parent;
So in this case, both children will have the prop "propsToPass"
<Parent>
{/* this.props.propsToPass will be available in this component */}
<Child></Child>
{/* this.props.propsToPass will be available in this component */}
<AnotherChild></AnotherChild>
</Parent>
You could do the same for your form.
I don't see like rendering Formik as children is good idea here, especially that you are supposed to render one form in such FormWrapper. I would use render props here, so here is basic example how you can do it.
Anyway, I still can't get your concept of re-inventing FormWrapper if Formik provides its own wrapper:
https://jaredpalmer.com/formik/docs/api/formik
interface FormWrapperProps extends FormikConfig<FormikValues> {
renderForm(props: FormWrapperProps): React.ReactNode
}
export const RegisterForm = (props: FormWrapperProps) => (
<form>
<input type="text"/>
<input type="text"/>
</form>
)
const FormWrapper: React.FC<FormWrapperProps> = (props) => {
return (
<div className="layout">
{/*here goes goes a Form from a different components*/}
{props.renderForm(props)}
</div>
)
}
const FormPage = () => {
const props = {} as FormWrapperProps
return (
<FormWrapper
{...props}
renderForm={(props: FormWrapperProps) => <RegisterForm {...props} />}
/>
)
}

Categories