I was using a library known as Swiper js. In there i saw something which i am unable to understand. Swiper is giving me a hook which returns all the data related to its state like activeSlide, isLast, isStart and many more without explicitly passing ref to that component.
// import Swiper core and required modules
import { Navigation, Pagination, Scrollbar, A11y } from 'swiper/modules';
import { Swiper, SwiperSlide } from 'swiper/react';
// Import Swiper styles
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
import 'swiper/css/scrollbar';
export default () => {
return (
<Swiper
modules={[Navigation, Pagination, Scrollbar, A11y]}
spaceBetween={50}
slidesPerView={3}
navigation
pagination={{ clickable: true }}
scrollbar={{ draggable: true }}
onSwiper={(swiper) => console.log(swiper)}
onSlideChange={() => console.log('slide change')}
>
<SwiperSlide>Slide 1</SwiperSlide>
<SwiperSlide>Slide 2</SwiperSlide>
<SwiperSlide>Slide 3</SwiperSlide>
<SwiperSlide>Slide 4</SwiperSlide>
...
</Swiper>
);
};
import { useSwiper } from 'swiper/react';
export default function SlideNextButton() {
const swiper = useSwiper();
return (
<button onClick={() => swiper.slideNext()}>Slide to the next slide</button>
);
}
As you can see above useSwiper
returns an object swiper
which has a method slideNext
. I want to create a component in a similar manner where i can access the state and update the state from outside without passing any props or refs just how swiper.js is doing.
I have tried to use context and importing the context but it didn't work.
You can create your own context which you can use in all child components.
Create a context
// MySwiper.js
import { createContext, useContext, useState, useCallback } from "react";
const MySwiperContext = createContext();
export const MySwiper = ({ children }) => {
const [value, setMyValue] = useState(10);
const myCustomMethod = useCallback(() => {
// Do things
console.log("my custom method");
}, []);
const overrideValue = useCallback((newValue) => {
setMyValue(newValue);
}, []);
return (
<MySwiperContext.Provider
// Things you want to expose to your custom hook
value={{
value,
myCustomMethod,
overrideValue,
}}
>
{children}
</MySwiperContext.Provider>
);
};
// Expose the context with a custom hook
export const useMySwiper = () => useContext(MySwiperContext);
Use the context
// App.js
import "./styles.css";
import { MySwiper, useMySwiper } from "./MySwiper";
// Needs to be a child of the `MySwiper` component
// for the `useMySwiper` hook to work
const MySwiperChildComponent = () => {
const { value, overrideValue, myCustomMethod } = useMySwiper();
return (
<div>
value from mySwiper {value}
<br />
<button onClick={() => overrideValue(value + 10)}>add 10</button>
<br />
<button onClick={() => myCustomMethod()}>trigger custom method</button>
</div>
);
};
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen test!</h2>
<MySwiper>
<MySwiperChildComponent />
</MySwiper>
</div>
);
}
Check out this code sandbox for a working example