I have this Codesandbox with a Hamburger menu that refuse to let onClick work.
This image show the simple menu with the Timeline link
(it's suppose to be text color white but Codesandbox refuses)
Clicking the link does not fire the onClick it's like it's being blocket by another component.
I have tested to remove the Component NavLinkPage that is rendered at the same time and then my Menu works. It's like it's blocking even it's set to be off screen.
I have tried to set e.g. the z-index but with no luck the only think that works is removing the:
<NavLinkPage close={close} />..
The simple Menu is the Component:
<SideMenu close={close} />..
NavLinkPage are controlled by #media (max-width: 1098px).. and will show on large screens only.
here is CollapseMenu.jsx code with NavLinkPage and NavLinkPage :
import React, { useRef, useCallback, useEffect } from 'react';
import styled from 'styled-components';
import { useSpring, animated } from 'react-spring';
import useOnClickOutside from './UseOnClickOutside';
import NavLinkPage from './NavLinkPage';
import SideMenu from './SideMenu';
const CollapseMenu = props => {
const { show, close } = props;
const { open } = useSpring({ open: show ? 0 : 1 });
const reference = useRef();
useOnClickOutside(reference, close, 'burgerMenu');
const escFunction = useCallback(
event => {
// only accept 27 if it's visible
if (event.keyCode === 27 && show === true) {
close();
}
},
[close],
);
useEffect(() => {
document.addEventListener('keydown', escFunction, false);
return () => {
document.removeEventListener('keydown', escFunction, false);
};
}, [escFunction]);
if (show === true) {
return (
<CollapseWrapper
style={{
transform: open
.interpolate({
range: [0, 0.2, 0.3, 1],
output: [0, -20, 0, -200],
})
.interpolate(openValue => `translate3d(0, ${openValue}px, 0`),
}}
>
<NavLinkPage close={close} />
<SideMenu close={close} />
</CollapseWrapper>
);
}
return null;
};
export default CollapseMenu;
const CollapseWrapper = styled(animated.div)`
background: #2d3436;
position: fixed;
left: 0;
right: 0;
width: 200px;
z-index: 100;
`;
Related
So I'm using react-visibility-sensor with react-spring to animate text sliding char by char from any side I want.
In my home page the animation is running smoothly, I use it twice one from the right side and another from the top side.
When I switch routes and go to another page the animation does not work.
I have my code divided in an "Title" component "Char" component and a custom hook "useAnimatedText".
Title component:
import React from "react";
import VisibilitySensor from "react-visibility-sensor";
import useAnimatedText from "../../hooks/useAnimatedText";
import Char from './Char'
const Title = ({title, side}) => {
// HERE I CALL A CUSTOM HOOK THAT WILL DIFINE IF THE ELEMENT IS VISIBLE OR NOT
// AND HANDLE THE ANIMATION WHEN NECESSARY
const [isVisible, onChange, objArray] = useAnimatedText(title)
let elements = objArray.map((item, i) => {
return(
<Char
key={i}
isVisible={isVisible}
item={item}
delay={400 + (i * 40)}
side={side}
/>
)
})
console.log(isVisible)
return(
<VisibilitySensor onChange={onChange} >
<span className="title-box">
<h1 className="my-heading divided-heading">
{elements}
</h1>
<hr className="title-ruller"></hr>
</span>
</VisibilitySensor>
)
}
export default Title
Char component:
import { useSpring, animated } from "react-spring"
const Char = (props) => {
const { isVisible, item, delay, isBouncy, side} = props
const [ref, addBounce] = useBounce()
let springConfig = {}
if (side === 'right') {
springConfig = {
to: {
opacity: isVisible ? 1 : 0,
translateX : isVisible ? '0px' : '1000px'
},
config: { mass:2, tension: 200, friction: 30},
delay: delay
}
}
else if (side === 'top') {
springConfig = {
to: {
opacity: isVisible ? 1 : 0,
translateY: isVisible ? '0px' : '-500px'
},
config:{ mass:2, tension: 250, friction: 35},
delay: delay
}
}
const spring = useSpring({...springConfig})
return(
<animated.span
style={ spring }
className={isVisible ? 'is-visible' : 'is-not-visible'}
>
{item.char === ' ' ? <span> </span> : item.char}
</animated.span>
)
}
export default Char
This is the custom Hook:
import { useState } from "react";
import { stringToArray } from '../helpers'
// HOOK THAT HANDLES THE TEXT ANIMATION BY SETTING A STATE OF VISIBILITY
function useAnimatedText(string) {
const [isVisible, setVisibility] = useState(false);
const onChange = visiblity => {
visiblity && setVisibility(visiblity);
};
let objArray = stringToArray(string)
return [isVisible, onChange, objArray]
}
export default useAnimatedText
I did a console.log(isVisible) and the value was true but it was rendering in the page the spring values as if it was false(not visible).
I really can´t understand where I'm going wrong here, the only problem I have is when I'm not at my main route, could it be because of react-router-dom?
If someone has any clue, let me know.
may I please know how do I change my mouse cursor to the pointer on mouseover, and back to the default in cytoscape.js and React.js?
Below is my code, which doesn't work. I've removed the parts which aren't relevant to the question
import React, { Fragment, useState } from 'react';
import CytoscapeComponent from 'react-cytoscapejs';
import Cytoscape from 'cytoscape';
const Network = (props) => {
let [ext_cy, setCy] = useState(null);
const [my_cursor, setCursor] = useState('default');
<CytoscapeComponent
elements={props.elements}
style={ {
height: sizeHeight + 'px',
cursor: my_cursor
} }
cy={cy => {
cy.on('add', 'node', _evt => {
cy.layout(layout).run()
cy.fit()
setCy(cy)
})
cy.on('mouseover', 'node', changeCursor('pointer'));
cy.on('mouseout', 'node', changeCursor('default'));
}}
stylesheet={stylesheet}
layout={layout}
pan={ { x: x, y: 80 } }
zoom={0.8}
minZoom={0.5}
maxZoom={2}
/>
Can't resize React-Player Video.
I change the width to any number and the video stays unchanged.
I am trying to optimize it for computer view and then add breakpoints to resize for smaller screens like phones.
Bellow is the file where I render the React-Player video inside a on which I apply the desired height and width I would like my react-player video to adopt.
import React, { useContext, useEffect, useState } from 'react'
import { makeStyles } from '#material-ui/core/styles'
import Modal from '#material-ui/core/Modal'
import { MovieContext } from './MovieContext'
import ReactPlayer from 'react-player'
import { getTrailer } from '../utils/movieDB'
// potential of adding controls
// import { Slider, Direction } from 'react-player-controls'
//slider to be implemented
//https://www.npmjs.com/package/react-player-controls#playericon-
const useStyles = makeStyles((theme) => ({
video: {
width: 'auto',
height: 'auto',
top: '25%',
right: '25%',
position: 'fixed',
[theme.breakpoints.down('xs')]: {},
},
}))
const styles = {
player: {
width: '300px',
},
}
export default function SimpleModal({ open }) {
const classes = useStyles(),
//receives movie from Home > DisplayCard > MovieContext
{ setOpenTrailer, movie, setMovie } = useContext(MovieContext),
[trailer, setTrailer] = useState(),
[key, setKey] = useState(),
[modalStyle] = useState()
useEffect(() => {
if (movie) {
getTrailer(movie).then((data) => {
setKey(data.videos.results[0].key)
setTrailer(data)
})
}
}, [movie])
const handleOpen = () => {
setOpenTrailer(true)
}
const handleClose = () => {
setOpenTrailer(false)
setMovie(undefined)
setTrailer(undefined)
setKey(undefined)
}
const renderVideo = (
<>
{key && (
<div className={classes.video}>
<ReactPlayer style={styles.player} url={`https://www.youtube.com/watch?v=${key}`} />
</div>
)}
</>
)
return (
<div>
<Modal
open={open || false}
onClose={handleClose}
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
>
{renderVideo}
</Modal>
</div>
)
}
Which is the proper way to set the dimensions on a react-player object?
Using the width and height props as such:
<ReactPlayer
width={“300px”}
url={`https://www.youtube.com/watch?v=${key}`} />
this code is from the react-player library. This made my video responsive
its from: https://github.com/cookpete/react-player
class ResponsivePlayer extends Component {
render () {
return (
<div className='player-wrapper'>
<ReactPlayer
className='react-player'
url='https://www.youtube.com/watch?v=ysz5S6PUM-U'
width='100%'
height='100%'
/>
</div>
)
}
}
----- CSS ------
.player-wrapper {
position: relative;
padding-top: 56.25% /* Player ratio: 100 / (1280 / 720) */
}
.react-player {
position: absolute;
top: 0;
left: 0;
}
I am trying to style some buttons based on whether they are 'active' or not, and also whether or not the use is hovering the mouse over them.
It works to some extent, however, it's behaving in a way that I don't fully understand.
How do I apply a conditional style to a component, based on its state, as well as based on user behavior?
I have an example in this SANDBOX
And the main JS file copied here:
demo.js
import React from "react";
import PropTypes from "prop-types";
//import { makeStyles } from "#material-ui/core/styles";
import { withStyles } from "#material-ui/styles";
import { Button } from "#material-ui/core";
const useStyles = theme => ({
root: {
backgroundColor: theme.palette.secondary.paper,
width: 500
},
pageButton: {
backgroundColor: "black",
color: "blue",
width: 30,
minWidth: 20,
"&:hover": {
backgroundColor: "green"
}
},
normalButton: {
width: 30,
minWidth: 20,
backgroundColour: "red"
}
});
class Feature extends React.Component {
constructor(props) {
super(props);
this.state = { currentPage: 0 };
}
handleClick(page) {
this.setState({ currentPage: page });
}
fetchPageNumbers() {
return [1, 2, 3];
}
render() {
const classes = this.props.classes;
return (
<div className={classes.root}>
{this.fetchPageNumbers().map((page, index) => {
return (
<div>
<Button
onClick={() => this.handleClick(page)}
key={page}
className={
this.state.currentPage === page
? classes.pageButton
: classes.normalbutton
}
>
{page}
</Button>
<Button
onClick={() => {}}
key={page * 20}
className={classes.normalButton}
>
{page * 20}
</Button>
</div>
);
})}
</div>
);
}
}
Feature.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(useStyles)(Feature);
There are two rows. The second row picks up the styles just fine.
The first row will only adhere when the button is clicked. I want to be able to set the state based on whether the current button is active (ie. state == buttonNumber), and also whether or not the user is hovering over any of the buttons.
How do I apply a conditional style to a component, based on its state, as well as based on user behavior?
For conditional style based on user behavior
I guess your current demand is when it's hovering.
"&:hover": {
// Hover styles
}
For conditional style based on params(props)
withStyles doesn't have access to the properties.
refer: issue: Can withStyles pass props to styles object? #8726
But there are multiple work-around solutions
1.use injectSheet HOC
notice that the useStyles in your code is actually not a hook
const styles = props => ({
root: {
width: props.size === 'big' ? '100px' : '20px'
}
})
or
const styles = {
root: {
width: props => props.size === 'big' ? '100px' : '20px'
}
}
with
const CustomFeature = ({size, classes}) => <Feature className={classes.root} />;
export default withStyles(styles)(CustomFeature);
2.use style hooks with params (for functional components)
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
root: {
width: props => props .size === "big" ? "100px" : "20px"
}
}));
const classes = useStyles();
or
import { makeStyles } from "#material-ui/core/styles";
const useStyles = params =>
makeStyles(theme => ({
root: {
width: params.size === "big" ? "100px" : "20px"
}
}));
const classes = useStyles(whateverParamsYouWant)();
In response to #keikai you can also pass in an object into the styles() hook (I was getting an error by just passing in props).
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
root: {
width: ({ size }) => (size === "big" ? "100px" : "20px")
}
}));
const classes = useStyles({ size });
I am new to React and learning how to animate styles. I have created the following animation that moves the element down 50px when the page renders. The props from, to, and config are part of the react-spring library.
import React, { Component } from 'react';
import sphere from '../img/sphere.png';
import { Spring, config } from 'react-spring'
import '../Sphere.css';
class BioSphere extends Component {
state = { top: 0 }
render() {
const float = (num) => {
if(num == 0) {
return 50;
this.setState({
top: 50
})
} else {
return 0;
}
};
return(
<div style={this.props} className="sphere">
<Spring
from = {{top: '0px'}}
to = {{top: `${float(this.state.top)}px`}}
config = {config.slow} >
{props => (
<div style={props}>
<img style={props} className='img' src={sphere} alt={' '}/>
</div>
)}
</Spring>
</div>
);
}
}
export default BioSphere;
Try creating a function that runs a conditional.
const conditional = (b,n1,n2) => b?n1:n2;
conditional(somebool,'0px','50px')