React Materialize Carousel Autoplay - reactjs

Given the code below, I would like to make the carousel autoplay within the said interval. However, being new in React, I have no idea on how to do it. I have tried searching for answers and have tried using carousel('next'), it didn't work. I am still finding answers and is hoping to clear this problem. Thanks!
import React from 'react';
import { Carousel } from 'react-materialize';
const Header = () => {
const imgArr = [
'https://picsum.photos/200/300?image=0',
'https://picsum.photos/200/300?image=1',
'https://picsum.photos/200/300?image=2',
];
return (
<Carousel
className='tabs'
options={{ duration: 100, indicators: true }}
images={imgArr}
/>
);
);

You could use this plugin instead: http://www.linxtion.com/demo/react-image-gallery/
You can use the prop slideInterval to decide when the next slide will occur.

Related

Mobile Safari Not Showing My Video Texture

I have a question similar to this one, but in my case, it's iOS causing troubles (not macOS, which I haven't tried yet), so I hope it's OK to post this as well. I tried to create a video texture in Three.js and can't bring it to work on mobile Safari (iOS 15.4). Here is my code, which I tried to tidy up as much as possible:
import React, { useEffect, useRef } from "react";
import * as THREE from "three";
import { Canvas } from "#react-three/fiber";
import "./styles.css";
const Screen = () => {
const meshRef = useRef();
useEffect(() => {
const vid = document.createElement("video");
vid.src = "/test.mp4";
vid.crossOrigin = "Anonymous";
vid.loop = vid.muted = vid.playsInline = true;
vid.play();
meshRef.current.material.map = new THREE.VideoTexture(vid);
});
return (
<mesh ref={meshRef}>
<planeGeometry attach="geometry" />
</mesh>
);
};
const App = () => {
return (
<Canvas camera={{ fov: 25 }}>
<Screen />
</Canvas>
);
};
export default App;
Please tell me if I'm doing something wrong here. The test.mp4 is from this URL. I also tried to place the video as HTML element, instead of creating it dynamically, then the video itself plays fine, but not the video texture.
Also, just curious, but why isn't meshRef.current available in a useEffect in the main component, but useEffect inside of Screen, which is placed inside of Canvas, is OK?
Apparently it's a problem with video file formats. Tried an example video from Three.js and it worked.
To those of you looking for the solution , you need to add
vid.playsInline=true;
for mobile ios devices.
I had the same problem. I had to set the 'playsinline' attribute in a very specific way.
video.playsinline= true did not work but video.setAttribute('playsinline', true)
did work.
Hope this helps

React/Framer Motion {variants} are not working?

So I started playing with Framer Motion in React and it's really nice.
I am able to create motions with initial/animate/exit, but for some reason I can't get variants to work?
So I've got this example:
<motion.span initial={{y:300}} animate={{y:0}} exit={{y: 300}} transition={transition} >A</motion.span>
and if I refresh the page (AnimatePresence initial is true, not false), it works, I get a letter that moves from y:300 to y:0 with a defined transition.
but then if I want to apply that to multiple letter, so transform it into variants like this:
import React, { useEffect, useState } from "react";
import { motion, useViewportScroll, useTransform } from "framer-motion";
import { Link } from "react-router-dom";
import Scrollbar from 'react-smooth-scrollbar';
import scrolldown from '../images/scrolldown.svg';
import work1 from '../images/p1.png';
import work2 from '../images/p3.png';
import work3 from '../images/p2.png';
const transition = { duration: 1.7, ease: [0.43, 0.13, 0.23, 0.96] };
const letter = {
initial: {
y: 300,
},
animate: {
y: 0,
transition: { duration: 1, ...transition },
},
};
const Home = () => (
and then use it like this:
<motion.span variants={letter}>A</motion.span>
it just won't work? am I missing something here?
I don't have any other motion defined/parent or anything. and it works when using inline code, but not with variants?
letter isn't moving on refresh/page change when using variants?
Thanks for taking the time guys!
so it seems that I needed to have a parent with these set:
<motion.div className="site-hero"
initial='initial'
animate='animate'
exit='exit'>
>
my bad for not reading the documentation properly.
maybe this helps anyone
You have to use like this
<motion.span variants={letter} initial="initial" animate="animate">
A
</motion.span>
The problem is that a span is an inline element so you can move it up or down. to fix it just added a style of display:inline-block. Now the span behaves as a block but yet still inline👍

Moving slider with Cypress

I've got a Slider component from rc-slider and I need Cypress to set the value of it.
<Slider
min={5000}
max={40000}
step={500}
value={this.state.input.amount}
defaultValue={this.state.input.amount}
className="sliderBorrow"
onChange={(value) => this.updateInput("amount",value)}
data-cy={"input-slider"}
/>
This is my Cypress code:
it.only("Changing slider", () => {
cy.visit("/");
cy.get(".sliderBorrow")
.invoke("val", 23000)
.trigger("change")
.click({ force: true })
});
What I've tried so far does not work.
Starting point of slider is 20000, and after test runs it goes to 22000, no matter what value I pass, any number range.
Looks like it used to work before, How do interact correctly with a range input (slider) in Cypress? but not anymore.
The answer is very and very simple. I found the solution coincidentally pressing enter key for my another test(date picker) and realized that pressing left or right arrow keys works for slider.
You can achieve the same result using props as well. The only thing you need to do is to add this dependency: cypress-react-selector and following instructions here: cypress-react-selector
Example of using {rightarrow}
it("using arrow keys", () => {
cy.visit("localhost:3000");
const currentValue = 20000;
const targetValue = 35000;
const increment = 500;
const steps = (targetValue - currentValue) / increment;
const arrows = '{rightarrow}'.repeat(steps);
cy.get('.rc-slider-handle')
.should('have.attr', 'aria-valuenow', 20000)
.type(arrows)
cy.get('.rc-slider-handle')
.should('have.attr', 'aria-valuenow', 35000)
})
#darkseid's answer helped guide me reach an optimal solution.
There are two steps
Click the slider's circle, to move the current focus on the slider.
Press the keyboard arrow buttons to reach your desired value.
My slider jumps between values on the sliders, therefore this method would work. (I am using Ion range slider)
This method doesn't require any additional depedency.
// Move the focus to slider, by clicking on the slider's circle element
cy.get(".irs-handle.single").click({ multiple: true, force: true });
// Press right arrow two times
cy.get(".irs-handle.single").type(
"{rightarrow}{rightarrow}"
);
You might be able to tackle this using Application actions, provided you are able to modify the app source code slightly.
Application actions give the test a hook into the app that can be used to modify the internal state of the app.
I tested it with a Function component exposing setValue from the useState() hook.
You have used a Class component, so I guess you would expose this.updateInput() instead, something like
if (window.Cypress) {
window.app = { updateInput: this.updateInput };
}
App: index.js
import React, { useState } from 'react';
import { render } from 'react-dom';
import './style.css';
import Slider from 'rc-slider';
import 'rc-slider/assets/index.css';
function App() {
const [value, setValue] = useState(20000);
// Expose the setValue() method so that Cypress can set the app state
if (window.Cypress) {
window.app = { setValue };
}
return (
<div className="App">
<Slider
min={5000}
max={40000}
step={500}
value={value}
defaultValue={value}
className="sliderBorrow"
onChange={val => setValue(val)}
data-cy={"input-slider"}
/>
<div style={{ marginTop: 40 }}><b>Selected Value: </b>{value}</div>
</div>
);
}
render(<App />, document.getElementById('root'));
Test: slider.spec.js
The easiest way I found assert the value in the test is to use the aria-valuenow attribute of the slider handle, but you may have another way of testing that the value has visibly changed on the page.
describe('Slider', () => {
it("Changing slider", () => {
cy.visit("localhost:3000");
cy.get('.rc-slider-handle')
.should('have.attr', 'aria-valuenow', 20000)
cy.window().then(win => {
win.app.setValue(35000);
})
cy.get('.rc-slider-handle')
.should('have.attr', 'aria-valuenow', 35000)
})
})
For whoever comes across this with Material UI/MUI 5+ Sliders:
First off, this github issue and comment might be useful: https://github.com/cypress-io/cypress/issues/1570#issuecomment-606445818.
I tried changing the value by accessing the input with type range that is used underneath in the slider, but for me that did not do the trick.
My solution with MUI 5+ Slider:
<Slider
disabled={false}
step={5}
marks
data-cy="control-percentage"
name="control-percentage"
defaultValue={0}
onChange={(event, newValue) =>
//Handle change
}
/>
What is important here is the enabled marks property. This allowed me to just click straight on the marks in the cypress test, which of course can also be abstracted to a support function.
cy.get('[data-cy=control-percentage]').within(() => {
// index 11 represents 55 in this case, depending on your step setting.
cy.get('span[data-index=11]').click();
});
I got this to work with the popular react-easy-swipe:
cy.get('[data-cy=week-picker-swipe-container]')
.trigger('touchstart', {
touches: [{ pageY: 0, pageX: 0 }]
})
.trigger('touchmove', {
touches: [{ pageY: 0, pageX: -30 }]
})

React functional component using the `useState` hook does not update onChange using ReactiveSearch

I am trying to use the ReactiveSearch component library to build a basic search application, and need to use the components as controlled component (https://reactjs.org/docs/forms.html). For all of the other filters I am working with, this is no problem, and the app detects changes and updates accordingly. However, for this DateRange component, it won't work. My working hypothesis is that it has something to do with the state value being an object rather than an array, but I can't find evidence to support that yet.
I've also tried using a regular class component, with the same result.
Link to Sandbox: https://codesandbox.io/s/ecstatic-ride-bly6r?fontsize=14&hidenavigation=1&theme=dark
Basic code snippet with no other filters
import React, { useState } from "react";
import {
ReactiveBase,
ResultsList,
DateRange,
SelectedFilters
} from "#appbaseio/reactivesearch";
const App = props => {
const [filterState, setFilterState] = useState({
DateFilter: { start: new Date(), end: new Date() }
});
return (
<div className="App">
<ReactiveBase
app="good-books-ds"
credentials="nY6NNTZZ6:27b76b9f-18ea-456c-bc5e-3a5263ebc63d"
>
<DateRange
value={filterState.DateFilter}
onChange={value => {
setFilterState({
...filterState,
DateFilter: {
start: value.start,
end: value.end
}
});
}}
componentId="DateFilter"
dataField="timestamp"
/>
<SelectedFilters />
</ReactiveBase>
</div>
);
};
export default App;
Just changing value to defaultValue worked for me (https://codesandbox.io/s/jolly-spence-1o8bv).
<DateRange
defaultValue={filterState.DateFilter}
onChange={value => {
setFilterState({
DateFilter: {
start: value.start,
end: value.end
}
});
}}
componentId="DateFilter"
dataField="timestamp"
/>
I also removed the DateFilter spread in your setFilterState, since your previous state was being fully overwritten regardless.
It turned out to be an underlying problem with how the ReactiveSearch library was comparing the dates, as well as not setting values properly. Will make a PR to fix it.

React execute script if window width

I have a button in React that executes a function onClick. I want to get rid of the button, and instead programmatically execute the function if window width < 1000px.
A restriction is that I can not add a plugin.
Here's what the code looks like...
// Do I need useState, useEffect?
import React, { PureComponent } from "react";
class MainNav extends PureComponent {
state = {
// Does something go here? What goes here and how do I use
// state to execute the function?
navIsCollapsed: false,
};
// this controls rendering of huge images
toggleShowImages() {
this.setState({
navIsCollapsed: !this.state.navIsCollapsed,
});
}
// I want this to be executed by width < 1000
handleSideNavToggle = () => {
this.toggleShowImages(); // controls if React renders components
document.body.classList.toggle("side-nav-closed");
}
Here's render the button that's currently executing the function. I want width < 1000 to programmatically execute its function.
// window width < 1000 should execute this function
<div onClick={this.handleSideNavToggle}>Don't render huge images</div>
// here are the images the function conditionally renders
<should show images &&
<div>Massive huge image</div>
<div>Massive huge image</div>
<div>Massive huge image</div>
>
I could use CSS media query to show or hide the massive images I don't want, but that's horrible use of React.
I've looked and tried to implement similar questions on SO that either invoke plugins, are out of date, or the use case is too different (for example, "re-render everything based on screen size"). I've also tried to React-ify vanilla javascript. This seems like it ought to be simple to do but I can't make it work.
Any React wizards out there who can answer with a clean, efficient solution?
Use the above method that Mathis Delaunay mentioned to get viewport/window width, then to get rid of that button. Just simply add a condition to whether render it or not and then watch on state changes to trigger the function.
Here I use hooks to do it
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
function App() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
function handleResize() {
setWidth(window.innerWidth);
}
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, [width]);
useEffect(() => {
width < 600 && handleSideNavToggle();
},[width]);
function handleSideNavToggle() {
console.log("toggle it");
}
return (
<div className="App">
{width > 600 && (
<button onClick={() => handleSideNavToggle()}>
Don't render huge images
</button>
)}
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Here is a working example. I set the width to be handled as 600 to make it easy to see.
https://codesandbox.io/s/react-hooks-counter-demo-w9wgv
Try looking at this answer, i think it is what your are searching for :
Get viewport/window height in ReactJS
You just need to check in the updateWindowDimension if the window.innerWidth is under 1000, if so, change the css button property to display : none; or visibility: hidden;.

Resources