Is there a way to access methods inside of an npm package? - reactjs

I'm currently building a website where I need to build a carousel. The carousel needs to have a 'progress bar' as the indicator for the current slide (like here: https://www.samsung.com/uk).
I'm familiar with react-responsive-carousel, but it doesn't have the functionality built in for the progress bar.
I've used state to effectively build a stopwatch to facilitate the progress bar inside my component.
Instead of using the built in autoplay functionality from react-responsive-carousel, I'd like to have a function that is triggered once the interval is finished to move on to the next slide.
The problem I'm having is, I'm not sure how to trigger this action. I've checked the docs, and it looks like I need to trigger onClickNext (see here, line 528), but I can't figure out how to do that.
I'm currently using a functional component, rather than a class based component, if that makes a difference. I just need to understand how I can trigger that action from my component.
Thanks

Maybe triggering the function inside of that class component using a ref is the way.
It seems to be the solution you're looking for.
import { Carousel } from "react-responsive-carousel";
import "react-responsive-carousel/lib/styles/carousel.min.css";
import { useEffect, useRef } from "react";
const App = () => {
const myRef = useRef();
useEffect(() => {
setTimeout(() => {
if (myRef) myRef.current.onClickNext();
}, 2000);
}, []);
return (
<Carousel ref={myRef}>
<div>
<p>Slide 1</p>
</div>
<div>
<p>Slide 2</p>
</div>
</Carousel>
);
};
export default App;

Related

React useeffect shows mounting of component in 2 times

i have a component names "Home" and i have a useEffect inside it which has a console.log("Home component mounted"). I just used a common useEffect hook. But when i initially render the page I getting the console log 2 times instead of showing it in the initial mounting of component. Can anyone tell me whats happening with my code. The code is as follows:
import React, { useEffect } from 'react';
const Home = () => {
useEffect(()=>{
console.log("Home component mounted")
})
return (
<div className="container">
<h1 className="h1">Home Page</h1>
</div>
)};
export default Home;
It's happening because in your app in strict mode. Go to index.js and comment strict mode tag. You will find a single render.
This happens is an intentional feature of the React.StrictMode. It only happens in development mode and should help to find accidental side effects in the render phase.
Or you can try to use this hook : useLayoutEffect
import React, { useLayoutEffect } from "react";
const Home = () => {
useLayoutEffect(() => {
console.log("Home component mounted");
}, []);
return (
<div className="container">
<h1 className="h1">Home Page</h1>
</div>
);
};
export default Home;
It is because of React.StrictMode
You don't have to worry- just that StrictMode runs your effect code twice(only during development, don't have to worry about production) to be able to catch bugs and memory leaks among other things
Read more: https://reactjs.org/docs/strict-mode.html
Screenshot here
useEffect() equivalent with componentDidMount() and componentDidUpdate(). This means when rendering your component, useEffect() will be called twice. If you want useEffect() only called one time, you just add the second parameter for it. It will as this.
useEffect(()=>{
console.log("Home component mounted")},[])
I hope this helpful for you!

Get the Gatsby Link destination and conditionally render exit animation with Framer Motion

I've built a small website to learn more about page transition with Gatsby and Framer Motion and Styled Components.
[SPOILER]: My problem to be solved is at the end of the code blocks
The way it's currently working is simple:
An homepage with a list of projects
export default function Home() {
return (
<Layout>
<Welcome />
<WorkList />
<Footer />
</Layout>
)
}
A project page template that generate each project thanks to createPages (here is a simplified version)
import React, { useState, useRef, useContext, useEffect } from "react"
import { Link } from "gatsby"
// Components
...
// Data
import Projects from "../data/works.json"
// Styles
...
// Variants
...
const Project = ({ pageContext }) => {
const project = Projects.find(({ id }) => id === pageContext.id)
// lots of functions here
return (
<Layout>
<ProjectWrapper>
<Container>
<ProjectContent>
<BackgroundLines />
<ProjectContentInner>
<ProjectHeader>
<!-- here the header logic -->
</ProjectHeader>
<ProjectBlocks>
<!-- here the content logic -->
</ProjectBlocks>
</ProjectContentInner>
<ProjectFooter>
<!-- here the footer logic -->
</ProjectFooter>
</ProjectContent>
</Container>
</ProjectWrapper>
</Layout>
)
}
export default Project
The Layout component is holding the navigation
// Components
import Header from "./header"
// Styles
import { GlobalStyle } from "../styles/globalStyles"
const Layout = ({ children }) => {
return (
<div className="app">
<GlobalStyle />
<Header />
<main>{children}</main>
</div>
)
}
export default Layout
and last but not least, the gatsby.browser.js wrapped with the AnimatePresence and the Context Provider
import React from "react"
import { AnimatePresence } from "framer-motion"
import { LocationProvider } from "./src/context/locationContext"
export const wrapPageElement = ({ element }) => (
<LocationProvider>
<AnimatePresence exitBeforeEnter>{element}</AnimatePresence>
</LocationProvider>
)
export const shouldUpdateScroll = () => {
return false
}
So what I want to do seemed easy but it turned out that is not (at least for me).
I've currently made a beautiful transition between 2 projects, similar to the one you could see in here.
If you scroll to the bottom of the page, you can see that the next project's header is shown as a preview and once you click on it, it will smoothly transition to the next project page.
Awesome.
BUT, but this transition is a problem when the user clicks on the link in the navigation that takes him to the home or to another page.
I don't want to have the same exit transition, where some elements disappear while others overlaps, and I don't want the same timing. I want to do something completely different, based on where I'm headed to.
What I thought of as a solution, is to conditionally render exit transition in framer motion, to have different exit animation based on some variables.
I want to be able to track the Link Destination before the component unmount in order to be able to conditionally render an exit transion in Framer Motion
Since, as you may have seen, the navigation isn't inside the project.js I tried with createContext and useContext, getting the location.pathname to have an origin state and a e.target.pathname on Link to have a destination state. This doesn't actually works because everything seems to get a rerender.
I just provided the pieces of codes that seemed crucial to understand the overall structure, but I can go deeper with the way I've built variants or the current exit animations.
I'm not sure if it will help but you can get the props as any React component in the wrapPageElement:
export const wrapPageElement = ({ element, props }) => {
console.log("props", props)
if(props.location.pathname==='/'){
//return some other animation stuff
}
return <LocationProvider {...props}>
<AnimatePresence exitBeforeEnter>{element}</AnimatePresence>
</LocationProvider>
}

Toggle text within a variable type function in React JS

Let's say I have a function:
import React from "react";
const Test = () => {
return (
<React.Fragment>
<h1>Hello World</h1>
</React.Fragment>
);
};
export default Test;
I want to toggle the Hello World text on and off with a button. How would I achieve this? I have looked at:
How React.js Toggle Button Works
React js onclick toggle class in map function
And none of them helped really. They used this.state, to which I got a type error, and then I started wondering if I should use a variable type function or not, as all the tutorials I've looked at use class instead. So my question is, how would I achieve toggling text in a variable type function?
If you need anymore information, or if my question was poorly phrased, please tell me. Any help is very much appreciated. Thank you!
this.state has no meaning in your functional component.
Instead you could do something like this:
import React, { useState } from "react";
const Test = () => {
const [showText, setShowText] = useState(false);
return (
<React.Fragment>
{showText && <h1>Hello World</h1>}
<button onClick={() => setShowText(!showText)}>Toggle</button>
</React.Fragment>
);
};
We use useState to create some state and set its initial value to false (i.e. The text should not be shown).
Then inside the onClick property of our button we can toggle the state value between true and false by setting showText and use this to conditionally render the text.
sandbox example

backgroundColor and onClick Wont Take Effect React JS In Basic React App

I am going through a React Learning Textbook that is explaining me about Hooks. The hooks part is working fine.
The author is illustrating how to customize Hooks with some easy to use style and related components.
I have the following code.
import React from 'react';
// import logo from './logo.svg';
import './App.css';
import StarRating from './components/StarRating';
import StarRating2 from './components/StarRating2';
import Headline from './components/Headline';
function App() {
return (
<article>
<Headline/>
<StarRating/>
<StarRating2
style={{ backgroundColor: "blue" }}
onClick={e => alert(" click")}
/>
</article>
);
}
export default App;
The component code is like this.
import { useState } from "react";
import React from "react";
import { FaStar } from "react-icons/fa";
const createArray = length => [...Array(length)];
const Star = ({ selected = false, onSelect = f => f }) => (
<FaStar color={selected ? "red" : "grey"} onClick={onSelect} />
);
const numberOfStarts = 10;
const numberDefaultState = 7;
function StarRating2({ totalStars = numberOfStarts })
{
//will hold the user’s rating
// create this variable by adding the useState hook directly to the StarRating component:
const [selectedStars, setSelectedStars] = useState(numberDefaultState);
return (
<>
<p>
This is Star Rating 2 - and it has some imporvements
</p>
{createArray(totalStars).map((n, i) => (
<Star
key={i}
selected={selectedStars > i}
onSelect= {
() => {
setSelectedStars(i + 1);
}
}
/>
))}
<p>
{selectedStars} of {totalStars} stars
</p>
</>
);
}
export default StarRating2;
Unfortunately, neither does the component display change its back ground color. Nor does it respond to a click. The app continues to run with no errors or anything. and I can see that the style properties set are visible in the component tree in the react developer tools in Firefox. So, the code is reflecting on the app for sure.
I am in the 6th chapter now, and so far, every chapter code has worked exactly as it is in the book. This one though, is not. I am unsure if this a wrong code (and perhaps, I should reach out to the author) or this is something that is no longer allowed and the book is simply out of date.
StarRating2 is a React component, you are passing couple of props to StarRating2 but you aren't using those props inside StarRating2 component. CSS styles and event handlers work on native DOM elements.
What you need to do is make use of the props that are passed to StarRating2 in from App component. You can apply the styles prop on the wrapper element that wraps all the JSX code of StarRating2 component and use onClick prop on the element which should react to the click event in some way.
To apply the background color in StarRating2 component, wrap the JSX code in a wrapper element, for example a div and then use the value of style prop on this wrapper element.
function StarRating2({ totalStars = numberOfStarts, style }) {
...
return (
<div style={style}>
...
</div>
);
}
To use the click handler, you will need to use the onClick prop and add it on any native DOM element.
You need to spread the props from the parent to a native react component , styles and eventListeners can only be attached to native components like div , button etc , if the Star component supports adding color and eventListeners through its , you can do ... rest in props and spread it to star component , if you need any help , send me a codesandbox , I will explain in that

Is there any problem to have many ReactDOM.render() in a ReactJS Project?

We are working on a Laravel project and it is written totally with JavaScript/HTML/JQuery. We are considering migrating to React as Laravel supports it. Is it OK to have many ReactDOM.render() ( per component) in the initial steps so we can progressively and fully convert our code base in the long run?
Is it necessary to access ref or just we can render each component like this:
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
ReactDOM.render(<App/>, document.querySelector("#form"))
and use it like this for every component:
// some html code and then
...
<div id="form"> </div>
<div id="modal"> </div>
<div id="navbar"> </div>
...
// rest of html code
Yes this is totally fine, when you call ReactDOM.render multiple times it will basically just triggers a diffing, very similar to the render method of a class component.
I actually wrote an article (with a tutorial) about "Integrate React with other applications and frameworks" that talks exactly about that topic.
The bottom line of this approach is that you can expose a global object with mount and unmount functions of your widget / mini-app and inside it call ReactDOM.render or ReactDOM.unmountComponentAtNode.
window.MyComponent = {
mount: (props, container) => {
ReactDOM.render(<Component {...props} />, container);
},
unmount: (container) => {
ReactDOM.unmountComponentAtNode(container);
}
}
Then in another part in the page you can call these functions, no matter what library or framework you are using obviously.
The beauty here, is that other react applications can use it as if it was a real component:
class MyComponentWrapper extends PureComponent {
// create a ref so we can pass the element to mount and unmount
myRef = React.createRef();
componentDidMount() {
// initial render with props
window.MyComponent.mount(this.props, this.myRef.current);
}
componentDidUpdate(prevProps) {
if(prevProps !== this.props){
window.MyComponent.mount(this.props, this.myRef.current);
}
}
componentWillUnmount(){
window.MyComponent.unmount(this.myRef.current);
}
render() {
return <div ref={this.myRef}></div>
}
}
Hope it helps.
Yes, that's completely fine. React is designed for gradual adoption.

Resources