i need to ask some question
I have 1 parent(index.js) and 2 childs (JobRequirement.js and JobList.js)
how can i send a data from job requirement to joblist?
here is my code
// JOBREQUIREMENT.JS
const JobRequirement = ({ isOpen, handleSelect }) => {
const [datas, setDatas] = useState([])
const loadData = () => {
axios.get('/bla')
.then((res) => {
setDatas(res.data.data)
})
}
useEffect(() => {
loadData()
}, [])
if (isOpen) {
return (
<Fragment>
<h5 className='mt-3 mb-2'>Job Requirements</h5>
<Row>
{datas.map((data) => (
<Col md='6' lg='4' key={data.id}>
<Card onClick={() => handleSelect(data.id)} className='text-center vertical-align-center mb-3'>
<CardBody>
<CardBody tag='h4'>{data.name}</CardBody>
</CardBody>
</Card>
</Col>
))}
</Row>
</Fragment>
)
} else return (<></>)
}
export default JobRequirement
// INDEX.JS
import { Fragment, useState } from 'react'
import JobRequirement from './JobRequirement'
import JobList from './JobList'
export default function JobRequirements() {
const [jobRequirement, setJobRequirement] = useState(true)
const [jobList, setJobList] = useState(false)
const selectJobRequirement = (data) => {
setJobRequirement(false)
setJobList(true, data)
}
const closeJobList = () => {
setJobRequirement(true)
setJobList(false)
}
return (
<div>
<Fragment>
<JobRequirement isOpen={jobRequirement} handleSelect={selectJobRequirement} />
<JobList isOpen={jobList} close={closeJobList} />
</Fragment>
</div>
)
}
// JOBLIST.JS
import { Fragment } from 'react'
import { Button, Row, Col, Card, CardBody } from 'reactstrap'
import { ChevronLeft } from 'react-feather'
const JobList = ({ isOpen, close, data }) => {
console.log(data)
if (isOpen) {
return (
<Fragment>
<div className='mt-2 mb-2'>
<Button size="sm" className='btn-icon' onClick={() => close()}><ChevronLeft size='15'/></Button> List of Job
</div>
<div>
<Row>
<Col md='6' lg='4'>
<Card className='text-center vertical-align-center mb-3'>
<CardBody>
<CardBody tag='h4'>Hello</CardBody>
</CardBody>
</Card>
</Col>
</Row>
</div>
</Fragment>
)
} else return (<></>)
}
export default JobList
I need to get a {data.id} from jobrequirement.js and use it in joblist.js
thankyou so much
Related
I'm creating an e-commerce website and I've run into an issue that I'm having trouble solving. The functionality to add products to the cart, route to CartScreen, and be able to increase/decrease quantity and remove items from the cart all work. However, if there is an item in the cart and I want to add another, instead of having both items in the cart it replaces the first item with the second and copies its quantity. Does anyone have any idea how I can fix this?
Here is my Product.js:
import { useEffect } from "react";
import Card from 'react-bootstrap/Card';
import Button from 'react-bootstrap/Button';
import { Link } from 'react-router-dom';
import Rating from './Rating';
import axios from 'axios';
import { useContext } from 'react';
import { Store } from '../Store';
function Product(props) {
const { product } = props;
const { state, dispatch: ctxDispatch } = useContext(Store);
const {
cart: { cartItems },
} = state;
const addToCartHandler = async (item) => {
const existItem = cartItems.find((x) => x._id === product._id);
const quantity = existItem ? existItem.quantity + 1 : 1;
const { data } = await axios.get(`/api/products/${item._id}`);
if (data.countInStock < quantity) {
window.alert('Sorry. Product is out of stock');
return;
}
ctxDispatch({
type: 'CART_ADD_ITEM',
payload: { ...item, quantity },
});
};
return (
<Card>
<Link to={`/product/${product.slug}`}>
<img src={product.image} className="card-img-top" alt={product.name} />
</Link>
<Card.Body>
<Link to={`/product/${product.slug}`}>
<Card.Title>{product.name}</Card.Title>
</Link>
<Rating rating={product.rating} numReviews={product.numReviews} />
<Card.Text>${product.price}</Card.Text>
{product.countInStock === 0 ? (
<Button variant="light" disabled>
Out of stock
</Button>
) : (
<Button onClick={() => addToCartHandler(product)}>Add to cart</Button>
)}
</Card.Body>
</Card>
);
}
export default Product;
Here is my CartScreen.js:
import { useContext } from 'react';
import { Store } from '../Store';
import { Helmet } from 'react-helmet-async';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import MessageBox from '../components/MessageBox';
import ListGroup from 'react-bootstrap/ListGroup';
import Button from 'react-bootstrap/Button';
import Card from 'react-bootstrap/Card';
import { Link, useNavigate } from 'react-router-dom';
import axios from 'axios';
export default function CartScreen() {
const navigate = useNavigate();
const { state, dispatch: ctxDispatch } = useContext(Store);
const {
cart: { cartItems },
} = state;
const updateCartHandler = async (item, quantity) => {
const { data } = await axios.get(`/api/products/${item._id}`);
if (data.countInStock < quantity) {
window.alert('Sorry. Product is out of stock');
return;
}
ctxDispatch({
type: 'CART_ADD_ITEM',
payload: { ...item, quantity },
});
};
const removeItemHandler = (item) => {
ctxDispatch({ type: 'CART_REMOVE_ITEM', payload: item });
};
const checkoutHandler = () => {
navigate('/signin?redirect=/shipping');
};
return (
<div>
<Helmet>
<title>Shopping Cart</title>
</Helmet>
<h1>Shopping Cart</h1>
<Row>
<Col md={8}>
{cartItems.length === 0 ? (
<MessageBox>
Cart is empty. <Link to="/">Go Shopping</Link>
</MessageBox>
) : (
<ListGroup>
{cartItems.map((item, i) => (
<ListGroup.Item key={i}>
<Row className="align-items-center">
<Col md={4}>
<img
src={item.image}
alt={item.name}
className="img-fluid rounded img-thumbnail"
></img>{' '}
<Link to={`/product/${item.slug}`}>{item.name}</Link>
</Col>
<Col md={3}>
<Button
onClick={() =>
updateCartHandler(item, item.quantity - 1)
}
variant="light"
disabled={item.quantity === 1}
>
<i className="fas fa-minus-circle"></i>
</Button>{' '}
<span>{item.quantity}</span>{' '}
<Button
variant="light"
onClick={() =>
updateCartHandler(item, item.quantity + 1)
}
disabled={item.quantity === item.countInStock}
>
<i className="fas fa-plus-circle"></i>
</Button>
</Col>
<Col md={3}>${item.price}</Col>
<Col md={2}>
<Button
onClick={() => removeItemHandler(item)}
variant="light"
>
<i className="fas fa-trash"></i>
</Button>
</Col>
</Row>
</ListGroup.Item>
))}
</ListGroup>
)}
</Col>
<Col md={4}>
<Card>
<Card.Body>
<ListGroup variant="flush">
<ListGroup.Item>
<h3>
Subtotal ({cartItems.reduce((a, c) => a + c.quantity, 0)}{' '}
items) : $
{cartItems.reduce((a, c) => a + c.price * c.quantity, 0)}
</h3>
</ListGroup.Item>
<ListGroup.Item>
<div className="d-grid">
<Button
type="button"
variant="primary"
onClick={checkoutHandler}
disabled={cartItems.length === 0}
>
Proceed to Checkout
</Button>
</div>
</ListGroup.Item>
</ListGroup>
</Card.Body>
</Card>
</Col>
</Row>
</div>
);
}
This is my Store.js:
import { createContext, useReducer } from 'react';
export const Store = createContext();
const initialState = {
cart: {
cartItems: localStorage.getItem('cartItems')
? JSON.parse(localStorage.getItem('cartItems'))
: [],
},
};
function reducer(state, action) {
switch (action.type) {
case 'CART_ADD_ITEM':
// add to cart
const newItem = action.payload;
const existItem = state.cart.cartItems.find(
(item) => item._id === newItem._id
);
const cartItems = existItem
? state.cart.cartItems.map((item) =>
item._id === existItem._id ? newItem : item
)
: [...state.cart.cartItems, newItem];
localStorage.setItem('cartItems', JSON.stringify(cartItems));
return { ...state, cart: { ...state.cart, cartItems } };
case 'CART_REMOVE_ITEM': {
const cartItems = state.cart.cartItems.filter(
(item) => item._id !== action.payload._id
);
localStorage.setItem('cartItems', JSON.stringify(cartItems));
return { ...state, cart: { ...state.cart, cartItems } };
}
default:
return state;
}
}
export function StoreProvider(props) {
const [state, dispatch] = useReducer(reducer, initialState);
const value = { state, dispatch };
return <Store.Provider value={value}>{props.children} </Store.Provider>;
}
Before in the CartScreen I was getting an Error of child in the list should be a unique key prop. But after fixing the issue still remains so I guess that wasn't the issue.
I am having an issue with Navigation Bar jumping to the top after selecting specific page. I want to side bar to stay same position after selecting the page. I found few similar questions here but the given solutions didn't solve my issue. Here the Code.
SideBarItem.js
import React, { useState } from 'react';
import classnames from 'classnames';
import { useRouter } from 'next/router';
import Link from 'next/link';
import useTranslation from 'next-translate/useTranslation';
import { AiOutlineLeft, AiOutlineDown } from 'react-icons/ai';
const SidebarHeader = ({ toggleSideBar, transKey }) => {
const { t } = useTranslation();
return (
<li
name={transKey}
id={transKey}
className={classnames('nav-small-cap', { 'dots-icon': !toggleSideBar })}>
{!toggleSideBar && <i className="mdi mdi-dots-horizontal"></i>}
{toggleSideBar && <span className="hide-menu">{t(transKey)}</span>}
</li>
);
};
const SidebarItem = ({
route,
icon,
toggleSideBar,
transKey,
isHeader,
subs,
}) => {
const { t } = useTranslation();
const router = useRouter();
const [isOpen, setIsOpen] = useState(false);
const handleToggle = () => {
setIsOpen(!isOpen);
};
const selectedClassName = router.pathname === route ? 'selected' : null;
return (
<>
{isHeader && (
<SidebarHeader
toggleSideBar={toggleSideBar}
transKey={transKey}
id={transKey}
/>
)}
{!isHeader && (
<li className={classnames('sidebar-item', selectedClassName)}>
<div className="sidebar-link clickable text-white-100 waves-effect waves-dark">
<i className={icon} style={{ color: 'white' }}></i>
{toggleSideBar && (
<div className="arrow-style">
{!subs && (
<Link href={route}>
<a className="hide-menu"> {t(transKey)}</a>
</Link>
)}
{subs && (
<>
<a className="hide-menu" onClick={handleToggle}>
{t(transKey)}
</a>
<div className="sidebar-arrow">
{isOpen ? <AiOutlineDown /> : <AiOutlineLeft />}
</div>
</>
)}
</div>
)}
</div>
{subs && (
<ul
className={classnames('collapse', 'first-level', {
show: isOpen,
})}>
{subs.map((subNavItem) => (
<SidebarItem
key={subNavItem.transKey}
{...subNavItem}
toggleSideBar={toggleSideBar}
/>
))}
</ul>
)}
</li>
)}
</>
);
};
export default SidebarItem;
SidebarLinks.js file
import React from 'react';
import navItems from '#constants/navItems';
import SidebarItem from './SidebarItem';
const SidebarLinks = (props) => {
return (
<nav className="sidebar-nav">
<ul id="sidebarnav" className="in">
{navItems.map((navItem) => (
<SidebarItem key={navItem.transKey} {...navItem} {...props} />
))}
</ul>
</nav>
);
};
export default SidebarLinks;
LayoutWithSidebar.js file
import React from 'react';
import useTranslation from 'next-translate/useTranslation';
import SidebarFooter from '#components/Sidebar/SidebarFooter';
import UserProfile from '#components/Sidebar/UserProfile';
import SidebarLinks from '#components/Sidebar/SidebarLinks';
import Styles from './styles';
const LayoutWithSidebar = ({ toggleSideBar, setToggleSidebar, btn }) => {
const { t } = useTranslation();
const handleEnterMouse = () => {
setToggleSidebar(true);
};
return (
<aside
className={`left-sidebar-style ${
toggleSideBar ? 'open-left-sidebar' : 'left-sidebar'
}`}
onMouseEnter={handleEnterMouse}
data-sidebarbg="skin5">
<div className="scroll-sidebar">
<UserProfile btn={btn} toggleSideBar={toggleSideBar} translation={t} />
<SidebarLinks btn={btn} toggleSideBar={toggleSideBar} translation={t} />
</div>
{(toggleSideBar || btn) && <SidebarFooter />}
<style jsx toggleSideBar={toggleSideBar}>
{Styles}
</style>
</aside>
);
};
export default LayoutWithSidebar;
App.js file
import React, { useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
import { Row, Col } from 'reactstrap';
import useTranslation from 'next-translate/useTranslation';
import AccountOverview from '#components/Dashboard/AccountOverview';
import Exposure from '#components/Dashboard/Exposure';
import PerformanceStats from '#components/Dashboard/PerformanceStats';
import CommissionAndBalance from '#components/Dashboard/CommissionAndBalance';
import MostRecentConversions from '#components/Dashboard/MostRecentConversions/index';
import Announcement from '#components/Dashboard/Announcement';
import TopPublishers from '#components/Dashboard/TopPublishers';
import ClickByCountries from '#components/Dashboard/TotalVisits/index';
import ClickPerDevice from '#components/Dashboard/OurVisitors/index';
import useShallowEqualSelector from '#hooks/useShallowEqualSelector';
import BaseLayout from '#layouts/BaseLayout';
import { formatNumber } from '#utils';
import routes from '#constants/routes';
import {
fetchAccountOverviewDataAction,
fetchPerformanceStatAction,
fetchAnnouncementAction,
fetchCommissionBalanceAction,
fetchExposuresAction,
fetchRecentConversionAction,
fetchTopPublishersAction,
fetchVisitorDataAction,
} from '#actions';
const Dashboard = () => {
const { t } = useTranslation();
const dispatch = useDispatch();
const [announcementRole, setAnnouncementRole] = useState('advertiser');
const [statFilter, setStatFilter] = useState('day');
const {
accountOverview,
exposures,
visitors,
commissionBalance,
recentConversions,
topPublishers,
performanceStatistics,
} = useShallowEqualSelector(({ stat }) => {
return stat;
});
const {
fetch: { list: announcements, status: announcementFetchStatus },
} = useShallowEqualSelector((state) => state.announcements);
const {
get: { currencyCode },
} = useShallowEqualSelector((state) => state.stat?.recentConversions);
useEffect(() => {
dispatch(fetchCommissionBalanceAction());
dispatch(fetchRecentConversionAction());
}, [dispatch]);
useEffect(() => {
dispatch(fetchAccountOverviewDataAction());
dispatch(fetchExposuresAction());
dispatch(fetchTopPublishersAction());
dispatch(fetchVisitorDataAction());
}, [dispatch]);
useEffect(() => {
dispatch(fetchPerformanceStatAction({ filter: statFilter }));
}, [dispatch, statFilter]);
useEffect(() => {
dispatch(
fetchAnnouncementAction({ role: announcementRole, page: 1, perPage: 4 })
);
}, [dispatch, announcementRole]);
return (
<BaseLayout
metaPageTitle={t('dashboard:pageTitle')}
pageTitle={t('dashboard:pageTitle')}
pageSubtitle={t('dashboard:pageSubtitle')}
breadcrumbPaths={[
{ url: routes.dashboard.url, text: t('common:home') },
{ text: t('dashboard:pageTitle') },
]}>
<div className="container-fluid">
{
<Row>
<Col sm={12}>
<AccountOverview
accountOverview={accountOverview.get.data}
isLoading={accountOverview.get.status === 'loading'}
t={t}
/>
</Col>
</Row>
}
{
<Row>
<Col sm={12}>
<PerformanceStats
isLoading={performanceStatistics.get.status === 'loading'}
setStatFilter={setStatFilter}
statFilter={statFilter}
performanceStatistics={performanceStatistics.get.data}
t={t}
/>
</Col>
</Row>
}
{
<Row>
<Col sm={12}>
<Exposure
exposures={exposures.get.data}
isLoading={exposures.get.status === 'loading'}
t={t}
/>
</Col>
</Row>
}
{
<Row>
<Col sm={12}>
<CommissionAndBalance
commissionBalance={commissionBalance.get.data}
isLoading={commissionBalance.get.status === 'loading'}
t={t}
/>
</Col>
</Row>
}
<Row>
<Col sm={12}>
<MostRecentConversions
isLoading={recentConversions.get.status === 'loading'}
recentConversions={recentConversions.get.data}
t={t}
currencyCode={currencyCode}
/>
</Col>
</Row>
<Row>
<Col sm={12}>
<div className="card-deck mb-4">
{
<Announcement
announcements={announcements}
announcementRole={announcementRole}
isLoading={announcementFetchStatus === 'loading'}
setAnnouncementRole={setAnnouncementRole}
t={t}
/>
}
<TopPublishers
isLoading={topPublishers.get.status === 'loading'}
topPublishers={topPublishers.get.data}
t={t}
formatNumber={formatNumber}
format
/>
</div>
</Col>
</Row>
{
<Row>
<Col sm={6}>
<ClickByCountries
isLoading={visitors.get.status === 'loading'}
totalVisitors={visitors.get.data?.totalVisitors}
t={t}
/>
</Col>
<Col sm={6}>
<ClickPerDevice
isLoading={visitors.get.status === 'loading'}
ourVisitors={visitors.get.data?.ourVisitors}
t={t}
/>
</Col>
</Row>
}
</div>
</BaseLayout>
);
};
export default Dashboard;
It would be great if you can assist.
P.S. I already looked through some answers here but it didn't work for me.
PLS check video link below
https://www.youtube.com/shorts/4xzlBfhQcKQ
From the video that you showed and the code you shared it seems that you wrapped your sidebar along with the entire application and pages components. If you want to avoid "rerendering" the sidebar, which is the thing that applies the "go to the top" effect, you should unwrap the layout with sidebar from the route changing, this will prevent this behaviour.
I want when I onClick element row, that show coin.id that element in console.log
import React, { useState, useEffect } from "react";
import { Col, Image, Row } from "react-bootstrap";
import "./Company.scss";
// * api
import { getCoin } from "../services/api";
// *spinner
import Loader from "./Loader";
const Company = () => {
const [selectedCoin, setSelectedCoin] = useState(null);
const [coins, setCoins] = useState([]);
useEffect(() => {
const fetchAPI = async () => {
const data = await getCoin();
setCoins(data);
};
fetchAPI();
}, []);
return (
<>
{coins.length > 0 ? (
coins.map((coin) => (
<Row
className={
selectedCoin === coin.id
? "p-2 border-top d-flex align-items-center company-list-single-active"
: "p-2 border-top d-flex align-items-center company-list-single"
}
onClick={() => {
setSelectedCoin(coin.id);
}}
key={coin.id}
>
<Col xxl="2" xl="2" lg="3" md="3" sm="2" xs="2">
<Image
src={coin.image}
alt={coin.name}
className="coin-image mx-2"
fluid
/>
</Col>
<Col>
<span>{coin.name}</span>
</Col>
</Row>
))
) : (
<Loader />
)}
</>
);
};
export default Company;
screenshot project
If you wish to add another call (like console.log()) in the anonymous function for the onClick event handler, you can
onClick={() => {
console.log(coin.id);
setSelectedCoin(coin.id);
}}
I was trying to render multiple props in a single component both the props are from different apis which are working together and the problem is i want to map the props in a single component to display a list of posts. someone said me do this by creating a variable (array) in my component. Then, spreading the properties (props) into the variable e.g myVariable.push(...posts, ...externalPosts). But i can't seem to figure out how do i achieve the results the Component renders another child component called to which i want to pass on the props.
App.js
import React, { useState, useEffect } from "react";
import axios from "axios";
import { Posts } from './components';
const App = () => {
const [ posts, setPosts ] = useState([]);
const [ postsExternal, setPostsExternal ] = useState([]);
const fetchPostsAll = () => {
axios.get(`http://localhost:2000/posts`).then(({ data }) => {
let externalPosts = [];
setPosts(data);
console.log(data);
data.map(({ external_id }) => {
axios
.get(`http://localhost:2000/posts${external_id}`)
.then(({ data }) => {
console.log(data);
externalPosts.push(data);
});
setPostsExternal(externalPosts);
});
});
}
useEffect(() => {
fetchPostsAll();
}, []);
return (
<div>
<Navbar/>
<Posts posts={posts} postsExternal={postsExternal} />
</div>
);
};
export default App;
Posts.js
import React from 'react';
import Post from './Post/Post';
const Posts = ({ posts, postsExternal }) => {
return (
<main>
<Container fluid>
<Row className="p-2">
{ posts.map((post) => (
<Col className="p-lg-4 p-sm-3" key={post.id} xs={6} sm={4} md={3} lg={3} xl={2}>
<Post post={post} postExternal={postsExternal}/>
</Col>
))}
</Row>
</Container>
</main>
);
};
export default Posts;
Post.js
import React from 'react';
const Post = ({ post, postExternal }) => {
return (
<Figure>
<span>{post.title}</span>
<span>{postExternal.rating}</span>
</Figure>
)
}
export default Post;
The problem is with the Posts.js file while mapping i want to map both the props and pass those single item props to Post.js
Do:
import React from 'react';
import Post from './Post/Post';
const Posts = ({ posts, postsExternal }) => {
return (
<main>
<Container fluid>
<Row className="p-2">
{ posts.map((post, index) => (
<Col className="p-lg-4 p-sm-3" key={post.id} xs={6} sm={4} md={3} lg={3} xl={2}>
<Post post={post} postExternal={postsExternal[index]}/>
</Col>
))}
</Row>
</Container>
</main>
);
};
export default Posts;
Edited:
import React from 'react';
import Post from './Post/Post';
const Posts = ({ posts, postsExternal }) => {
return (
<main>
<Container fluid>
<Row className="p-2">
{posts.length !== 0 && postsExternal.length !== 0 && posts.map((post, index) => (
<Col className="p-lg-4 p-sm-3" key={post.id} xs={6} sm={4} md={3} lg={3} xl={2}>
<Post post={post} postExternal={postsExternal[index]}/>
</Col>
))}
</Row>
</Container>
</main>
);
};
export default Posts;
Make sure your data is loaded.
fetchPostsAll function:
const fetchPostsAll = () => {
axios.get(`http://localhost:2000/posts`)
.then(({ data }) => {
console.log(data);
const externalPosts = data.map(({ external_id }) => {
return axios
.get(`http://localhost:2000/posts${external_id}`)
.then(({ data }) => {
return data;
});
})
Promise
.all(externalPosts)
.then(externalPosts => {
setPosts(data);
setExternalPosts(externalPosts);
});
})
;
}
You just don't desctructure the props and pass it as is.
import React from 'react';
import Post from './Post/Post';
const Posts = (props) => {
const { posts } = props;
return (
<main>
<Container fluid>
<Row className="p-2">
{ posts.map((post) => (
<Col className="p-lg-4 p-sm-3" key={post.id} xs={6} sm={4} md={3} lg={3} xl={2}>
<Post {...props} post={post}/>
</Col>
))}
</Row>
</Container>
</main>
);
};
export default Posts;
And you can do this in your App.js
import React, { useState, useEffect } from "react";
import axios from "axios";
import { Posts } from './components';
const App = () => {
const [ posts, setPosts ] = useState([]);
const [ postsExternal, setPostsExternal ] = useState([]);
const fetchPostsAll = () => {
axios.get(`http://localhost:2000/posts`).then(({ data }) => {
let externalPosts = [];
setPosts(data);
console.log(data);
data.map(({ external_id }) => {
axios
.get(`http://localhost:2000/posts${external_id}`)
.then(({ data }) => {
console.log(data);
externalPosts.push(data);
});
setPostsExternal(externalPosts);
});
});
}
useEffect(() => {
fetchPostsAll();
}, []);
const props = { posts, postsExternal };
return (
<div>
<Navbar/>
<Posts {...props} />
</div>
);
};
export default App;
Before diving to the main problem, my use case is I am trying to handle the scroll to a desired section. I will have navigations on the left and list of form sections relative to those navigation on the right. The Navigation and Form Section are the child component. Here is how I have structured my code
Parent.js
const scrollToRef = ref => window.scrollTo(0, ref.current.offsetTop);
const Profile = () => {
const socialRef = React.useRef(null);
const smsRef = React.useRef(null);
const handleScroll = ref => {
console.log("scrollRef", ref);
scrollToRef(ref);
};
return (
<>
<Wrapper>
<Grid>
<Row>
<Col xs={12} md={3} sm={12}>
<Navigation
socialRef={socialRef}
smsRef={smsRef}
handleScroll={handleScroll}
/>
</Col>
<Col xs={12} md={9} sm={12}>
<Form
socialRef={socialRef}
smsRef={smsRef}
/>
</Col>
</Row>
</Grid>
</Wrapper>
</>
);
};
Navigation.js(child component)
I tried using forwardRef but seems like it only accepts one argument as ref though I have multiple refs.
const Navigation = React.forwardRef(({ handleScroll }, ref) => {
// it only accepts on ref argument
const items = [
{ id: 1, name: "Social connections", pointer: "social-connections", to: ref }, // socialRef
{ id: 2, name: "SMS preference", pointer: "sms", to: ref }, // smsRef
];
return (
<>
<Box>
<UL>
{items.map(item => {
return (
<LI
key={item.id}
active={item.active}
onClick={() => handleScroll(item.to)}
>
{item.name}
</LI>
);
})}
</UL>
</Box>
</>
);
});
export default Navigation;
Form.js
I do not have idea on passing multiple refs when using forwardRef so for form section I have passed the refs as simple props passing.
const Form = ({ socialRef, smsRef }) => {
return (
<>
<Formik initialValues={initialValues()}>
{({ handleSubmit }) => {
return (
<form onSubmit={handleSubmit}>
<Social socialRef={socialRef} />
<SMS smsRef={smsRef} />
</form>
);
}}
</Formik>
</>
);
};
Social.js
const Social = ({ socialRef }) => {
return (
<>
<Row ref={socialRef}>
<Col xs={12} md={3}>
<Label>Social connections</Label>
</Col>
<Col xs={12} md={6}></Col>
</Row>
</>
);
};
Can anyone help me at passing multiple refs so when clicked on the particular navigation item, it should scroll me to its respective component(section).
I have added an example below. I have not tested this. This is just the idea.
import React, { createContext, useState, useContext, useRef, useEffect } from 'react'
export const RefContext = createContext({});
export const RefContextProvider = ({ children }) => {
const [refs, setRefs] = useState({});
return <RefContext.Provider value={{ refs, setRefs }}>
{children}
</RefContext.Provider>;
};
const Profile = ({ children }) => {
// ---------------- Here you can access refs set in the Navigation
const { refs } = useContext(RefContext);
console.log(refs.socialRef, refs.smsRef);
return <>
{children}
</>;
};
const Navigation = () => {
const socialRef = useRef(null);
const smsRef = useRef(null);
const { setRefs } = useContext(RefContext);
// --------------- Here you add the refs to context
useEffect(() => {
if (socialRef && smsRef) {
setRefs({ socialRef, smsRef });
}
}, [socialRef, smsRef, setRefs]);
return <>
<div ref={socialRef}></div>
<div ref={smsRef}></div>
</>
};
export const Example = () => {
return (
<RefContextProvider>
<Profile>
<Navigation />
</Profile>
</RefContextProvider>
);
};