Styled component with conditional calc - javascript

Currently I have the value being passed from the component
<Img $marginTop= {entry?.intersectionRatio} src={imgUrl} alt="" />
The code below is a simple statemnt which check if $marginTop is true (not null), then it should calculate calc($marginTop*-10)vh, else it should set margin-top as 0px. But the code below seems to fail to obtain the $marginTop value.
const Img = styled.img<{$marginTop : number | undefined}>`
margin-top: ${({ $marginTop }) => ($marginTop ? "calc($marginTop*-10)vh" : "0px")};
`
What is the correct way of achieving this?

Related

how to check the height of my component with hook ref from react?

I'm trying to check if the height of my button is 50 to display a different spinner but even the height being 50 displays SpinnerTwo, does anyone know the problem?
const Button = styled.button`
height: 50px;
`
const ButtonLoading(){
const refButton = useRef<HTMLButtonElement | null>(null);
return(
<Button ref={refButton} onClick={onClick} >
{refButton.current?.clientHeight === 50 ? <SpinnerOne /> : <SpinnerTwo />}
</Button> )
}
I thought was more easy to get element's height... Anyway you can't use a ref to do that.
You have to use ReactDOM.findDOMNode in combination with ref.
But is not sufficient because you have also to store this value into a state variable to active re-rendering after React renders first time the button (to get height).
So the code would be:
const [height, setHeight] = useState(); //<-- this to store the height
let refButton = useRef(); //<-- here the ref
useEffect(() => { //<-- here useEffect to store height into state var
setHeight(ReactDOM.findDOMNode(refButton.current).getBoundingClientRect().height);
}, []);
Then the rendering:
<button
ref={refButton1}
style={{ height: 50 }}
type="button"
onClick={() => {}}
>
{height === 50 ? "A" : "B"}
</button>
I made an example with 2 buttons: 1 with height = 50 and the other with height = 51. Here the codesandbox

React intersection observer does not work when responsive

I'm using react-intersection-observer in order to make some animations when the component is in view.
It works cool, but, when i try to go to a mobile screen, like, 633px width and 400px height, it does not work, and i really don't know why.
Let me show you the code
So, what i'm doing here, is that, i want to know when the user is seeing 45% of the component, but, it gives false always, is it because this component is quite big, probably its height is 750px or even more and the height of the screen of the phone is only 400px ? i don't know... I'm just trying to understand why it doens't work
const DifferentWorks = () => {
const [scrollY, setScrollY] = useState(0);
const { inView, ref } = useInView({ threshold: 0.45 });
useEffect(() => {
scrollYProgress.onChange(n => setScrollY(n));
}, [inView, scrollYProgress, scrollY]);
console.log(inView)
return (
<div ref={ref}>
<DifferentWorksHero>
</DifferentWorksHero>
</div>
);
};
export default DifferentWorks;
And let me show you what is the output of the console.log(inView)
I've scrolled all the component, from bottom to top, and this is the output
Always false..
What could be generating that error ? why it doesn't work when i change the size of the screen ?, specifally when the width is 663px and the height is under 500px

Making two Component same height when one is a array map

I am learning React and Redux and now I have this problem.
Here's a codesandbox
I want this two Component to be side by side and always have the same height even if Component2 grow larger since it's a map.
Try like this:
Search for book title "dep"
Watch the log grow pushing down the screen
Here's an image showing the Component2 getting larger then Component1 and I don't want that I have added style={{overflowY:"scroll"} to Component2 but don't understand why it pushes down anyway.
I tried using FlexBox but it's not working:
.row {
display: flex; /* equal height of the children */
}
.col {
flex: 1; /* additionally, equal width */
padding: 1em;
border: solid;
}
I don't want to set a fixed height.
looks like you need to do more CSS here.
Try to add a max-height: 300px in that component that have the overflow-y.
I've managed to solve this without setting height manually.
So, I've added a ref for the form.
this.formRef = React.createRef();
Used ref into the form tag.
<form ref={this.formRef}
And added an extra property to the state:
formHeight: "200px"
At componentDidMount hook I've assigned the height of the form into the state.
componentDidMount() {
this.setState(
(prevState) => ({
localBook: {
...prevState.localBook
},
formHeight:
this.formRef.current.parentElement.clientHeight.toString() + "px"
}),
() => {}
);
}
At your logger component I've added another style from props.
<div style={{ overflowY: "scroll", maxHeight: props.maxHeight }}>
And passed the prop from the parent:
<EnhancedTable maxHeight={this.state.formHeight} />
Demo at CodeSandbox.
Result:

why scroll down navigation bar is not changing the color?

here is my sample code
in the browser i want to scroll down the page the the navbar will say what color i am showing.
<div style={{height: "800px"}}>
<h2 style={{backgroundColor: `${nav}`,
position: "fixed",
width: "100%"
}}
>
NaveBar {nav ? "red" : "blue"}!
</h2>
</div>
it's somewhat not changing the name of the title and color also.i just dun know where is the problem.
can somebody help me on this please?
You initialized the state with a string useState("red");
and then you update the state to an object with setNav({ back });
To solve this just change it to setNav(back)
By the way - listening to scroll-events can be laggy, so you might want to "throttle" the event.
import throttle from lodash or just copy paste this function:
https://gist.github.com/abhinavnigam2207/a147abe0213d60467abacd33db7c6d2e
Then you use it by wrapping your function into it, like this:
useEffect(() => {
window.addEventListener(
"scroll",
throttle(() => {
const back = window.scrollY < 70 ? "red" : "blue";
setNav(back);
}, 100)
);
});

How do I (correctly) check whether an element is within the viewport in React?

In a functional react component, I'm trying to check whether a call to action button (a different component) is within the viewport. If it's not, I want to display a fixed call to action button at the bottom of the viewport, which shows/hides, depending on whether the other button is visible.
I can do this using a combination of Javascript and react hooks, but although the code works in some components in my app, it doesn't work in others; I'm guessing due to react lifecycles.
I'm also aware that this is NOT the way I should be doing things in react, so would prefer to achieve the same result, but in a proper 'react way'.
I've been looking at using refs, but ideally wanted to avoid having to change my functional component to a class, as I'd like to use react hooks for the show/hide of the fixed cta. However, if this is a requirement in order to get the functionality I want, I could go for that.
Here's what I've got so far - basically, I want to replace document.querySelector with a react method:
useEffect(() => {
const CTA = document.querySelector('#CTANextSteps');
const ApplyStyle = () => (isInViewport(CTA) ? setVisible(false) : setVisible(true));
ApplyStyle();
window.addEventListener('scroll', ApplyStyle);
window.addEventListener('resize', ApplyStyle);
return function cleanup() {
window.removeEventListener('scroll', ApplyStyle);
window.removeEventListener('resize', ApplyStyle);
};
});
const isInViewport = (elem) => {
const bounding = elem.getBoundingClientRect();
return (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
As mentioned above, this function works in some areas of the app without issue, but doesn't in others; I get a Cannot read property 'getBoundingClientRect' of null error. I was surprised it worked at all, but rather than tinkering with it to try and get it working everywhere, I want to rewrite it properly.
As always, any assistance would be much appreciated. Thanks.
I was able to do it with the depedency react-visibility-sensor#5.1.1
I followed the tutorial in this link and it worked fine with me.
I don't know if this is the correct way to do it, but it works!
Here is the link https://www.digitalocean.com/community/tutorials/react-components-viewport-react-visibility-sensor
I'll put an example just in case the previous link ever goes out.
import React, { Component } from 'react';
import VisibilitySensor from 'react-visibility-sensor';
class VisibilitySensorImage extends Component {
state = {
visibility: false
}
render() {
return (
<VisibilitySensor
onChange={(isVisible) => {
this.setState({visibility: isVisible})
}}
>
<img
alt={this.props.alt}
src={this.props.src}
style={{
display: 'block',
maxWidth: '100%',
width: '100%',
height: 'auto',
opacity: this.state.visibility ? 1 : 0.25,
transition: 'opacity 500ms linear'
}}
/>
</VisibilitySensor>
);
}
}
export default VisibilitySensorImage;

Categories

Resources