React: Fade not working - css

I'm using this code from here: http://buildwithreact.com/article/fade-in-image-recipe
currently have it as my component:
<ImageComponent src="https://docs.google.com/uc?id=0B0huBtqYaof7NFV6Nnpkalk5cEU" />
Now when I go to google chrome and inspect the element, it has the class names of image and image-loaded but when take a look at the css, there is no css even though I added it to my style sheet. Does anyone know how to fix this?
.image { opacity: 0; transition: opacity 500ms ease-in; }
.imageloaded { opacity: 1; }
Here is the css I imported(code above)
import React, { Component } from 'react';
import ImageComponent from './image.component.jsx';
import styles from './css/Header.css';
export default class Home extends Component {
constructor() {
super();
this.state = {
lightboxIsOpen: false,
currentImage: 0,
}
this.closeLightbox = this.closeLightbox.bind(this);
this.gotoNext = this.gotoNext.bind(this);
this.gotoPrevious = this.gotoPrevious.bind(this);
}
return(
<div>
<Grid>
<div>
<ImageComponent src="https://docs.google.com/uc?id=0B0huBtqYaof7NFV6Nnpkalk5cEU" />
</div>
</Grid>
</div>
)
}
Here is the component for ImageComponent
import classNames from 'classnames';
import React, { Component } from 'react';
import ReactDOM, { render } from 'react-dom';
const ImageComponent = React.createClass({
getInitialState: function() {
return {
loaded: false
};
},
onImageLoad: function() {
if (this.isMounted()) {
this.setState({ loaded: true });
}
},
componentDidMount: function() {
var imgTag = ReactDOM.findDOMNode(this.refs.img);
var imgSrc = imgTag.getAttribute('src');
var img = new window.Image();
img.onload = this.onImageLoad;
img.src = imgSrc;
},
render: function() {
var { className, ...props } = this.props;
var imgClasses = 'image';
var rootClassName = classNames(className, 'image', {
'imageloaded': this.state.loaded,
});
return (
<img ref="img" {...props} className={rootClassName} />
);
}
});
export default ImageComponent;

Try passing image url as props to imagecomponent and directly attach it to img element.

Related

crop image with react - customize react-easy-crop styling

I'm trying to make a very simple react component that would crop images with react-easy-crop. Apparently it is possible to customize the style of react-easy-crop module with style prop that takes 3 objects: containerStyle, mediaStyle and cropAreaStyle.
This is the default layout:
I want to expand cropArea to full width of its container and to fit media in it by height (so that we don't see the part of the original image outside of cropArea) but can't figure out how to do it. The cropAreaStyle object doesn't seem to affect width or height since it is calculated and injected in the module file (even after setting disableAutomaticStylesInjection to true).
import React from 'react'
import ReactDOM from 'react-dom'
import Cropper from 'react-easy-crop'
import './styles.css'
class App extends React.Component {
state = {
imageSrc:
'https://img.huffingtonpost.com/asset/5ab4d4ac2000007d06eb2c56.jpeg?cache=sih0jwle4e&ops=1910_1000',
crop: { x: 0, y: 0 },
zoom: 1,
aspect: 1 / 1,
style: { containerStyle: { position: "absolute", top: "0", width: "calc(100% - 2px)", height: window.innerWidth, overflow: "hidden", border: "1px solid black" },
mediaStyle: { height: "100%", display: "block" },
cropAreaStyle: {position: "absolute", top: "0", border: "1px solid black", width: "100%", height: "100%" }}
}
onCropChange = (crop) => {
this.setState({ crop })
}
onCropComplete = (croppedArea, croppedAreaPixels) => {
console.log(croppedArea, croppedAreaPixels)
}
onZoomChange = (zoom) => {
this.setState({ zoom })
}
render() {
return (
<div className="App">
<div className="crop-container">
<Cropper
image={this.state.imageSrc}
crop={this.state.crop}
zoom={this.state.zoom}
aspect={this.state.aspect}
onCropChange={this.onCropChange}
onCropComplete={this.onCropComplete}
onZoomChange={this.onZoomChange}
style={this.state.style}
disableAutomaticStylesInjection={true}
/>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
This is what I'm trying to achieve:
The black square is cropArea that I can't resize...
I want cropArea to remain square.
Is there an easy way to do this, without changing the module file?
The solution with another module is acceptable also
Thanks in advance
I tried to use the object cropAreaStyle but it's not working, instead use the prop cropSize and don't pass the prop aspect.
In order to get the height of the media pass the prop onMediaLoaded:
onMediaLoad = (mediaSize) => {
this.setState({
cropHeight: mediaSize.height,
});
};
App.js
import React from 'react';
import ReactDOM from 'react-dom';
import Cropper from 'react-easy-crop';
import './style.css';
class App extends React.Component {
state = {
imageSrc:
'https://img.huffingtonpost.com/asset/5ab4d4ac2000007d06eb2c56.jpeg?cache=sih0jwle4e&ops=1910_1000',
crop: { x: 0, y: 0 },
zoom: 1,
cropHeight: 0,
};
onCropChange = (crop) => {
this.setState({ crop });
};
onCropComplete = (croppedArea, croppedAreaPixels) => {
console.log(croppedArea, croppedAreaPixels);
};
onZoomChange = (zoom) => {
this.setState({ zoom });
};
onMediaLoad = (mediaSize) => {
this.setState({
cropHeight: mediaSize.height,
});
};
render() {
const cropSize = {
height: `${this.state.cropHeight}px`,
width: '100%',
};
return (
<div className="App">
<div className="crop-container">
<Cropper
image={this.state.imageSrc}
crop={this.state.crop}
zoom={this.state.zoom}
onCropChange={this.onCropChange}
onCropComplete={this.onCropComplete}
onZoomChange={this.onZoomChange}
onMediaLoaded={this.onMediaLoad}
cropSize={cropSize}
/>
</div>
</div>
);
}
}
export default App;
Demo: https://stackblitz.com/edit/react-4zmgud
It seems that what you need is the objectFit property set to vertical-cover.
See this demo: https://codesandbox.io/s/crazy-liskov-04u7m0

How can I create horizontal and vertical animation slider using react-stack-cards in ReactJs?

import React, { Component } from 'react'
import { ToggleCard, TinderLikeCard, StackCard } from 'react-stack-cards'
class Card extends React.Component {
constructor(props) {
super(props)
this.state = {
directionTinder: "swipeCornerDownRight",
directionToggle: "sideSlide",
directionStack: "topRight",
isOpen: false
}
this.Tinder = null
}
onTinderSwipe() {
this.Tinder.swipe()
}
onToggle() {
this.setState({ isOpen: !this.state.isOpen })
}
render() {
const {index, pic, name}=this.props.property
return (
<div className={`card-${index}`}>
<h1>{index}</h1>
<TinderLikeCard
images={pic}
width="550"
height="450"
direction={this.state.directionTinder}
duration={400}
ref={(node) => this.Tinder = node}
className="tinder"
>
</TinderLikeCard>
<button onClick={this.onTinderSwipe.bind(this)}>Swipe</button>
<h1>{name}</h1>
</div>
);
}
}
export default Card

Reactjs Media query application

I have a separate App.css file that has global css attributes and have classes for responsiveness. The issue is I want to render elements differently for separate devices but can't seem to figure out how to do that as using conditionals isn't applying as such.
import UserItem from "./UserItem";
import Spinner from "../layout/Spinner";
import PropTypes from "prop-types";
const Users = ({ users, loading }) => {
if (loading) {
return <Spinner />;
} else {
return (
<div style={userStyle} className='body'>
{users.map((user) => {
return <UserItem key={user.id} user={user} />;
})}
</div>
);
}
};
const windowWidth = window.innerWidth;
Users.propTypes = {
users: PropTypes.array.isRequired,
loading: PropTypes.bool.isRequired,
};
const userStyle = {
display: "grid",
gridTemplateColumns: "repeat(3, 1fr)",
gridGap: "1rem",
};
export default Users;
My css #media query which I am trying to apply to effect change on a small device.
/* Mobile Styles */
#media (max-width: 700px) {
.hide-sm {
display: none;
}
}
How do I implement this #media css style so that it can render the page differents through jsx?
You can use material ui. that will fulfil your requirement. Please check this example:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Typography from '#material-ui/core/Typography';
import { green } from '#material-ui/core/colors';
const useStyles = makeStyles(theme => ({
root: {
padding: theme.spacing(1),
[theme.breakpoints.down('sm')]: {
backgroundColor: theme.palette.secondary.main,
},
[theme.breakpoints.up('md')]: {
backgroundColor: theme.palette.primary.main,
},
[theme.breakpoints.up('lg')]: {
backgroundColor: green[500],
},
},
}));
export default function MediaQuery() {
const classes = useStyles();
return (
<div className={classes.root}>
<Typography variant="subtitle1">{'down(sm): red'}</Typography>
<Typography variant="subtitle1">{'up(md): blue'}</Typography>
<Typography variant="subtitle1">{'up(lg): green'}</Typography>
</div>
);
}
Material UI
You can use following example too.
class Card extends Component {
constructor() {
super();
this.mediaQuery = {
desktop: 1200,
tablet: 768,
phone: 576,
};
this.state = {
windowWidth: null
};
}
componentDidMount() {
window.addEventListener('resize', () => {
this.setState({windowWidth: document.body.clientWidth})
});
}
render() {
return (
<div style={{
width: this.state.windowWidth > this.mediaQuery.phone
? '50%'
: '100%',
//more styling :)
}}>
<!-- <Card> contents -->
</div>
);
}
}
Source
I suggest that use CSS #media query to make responsive layouts.
But if you insist on implement with JS and React you should get windowWidth after component mounted. You can use useEffect hook to do so and save value in a state:
const [windowWidth, setWindowWidth] = useState('');
useEffect(() => {
setWindowWidth(window.innerWidth) // or better one -> window.clientWidth
});

reactstrap close Nav when link clicked

I'm sure this has been asked before however, I can't find the answer. How do you get the Nav menu to close when you click on a NavLink in reactstrap or is this still in development?
Reactstrap has an isOpen parameter in state, so you need to set it to false
constructor(props) {
super(props);
this.closeNavbar = this.closeNavbar.bind(this);
this.state = {
isOpen: false
};
}
closeNavbar() {
this.setState({
isOpen: false
});
}
// and in Link or a element add onClick handler like this
<Link to="/" onClick={closeNavbar}>Home</Link>
Here is the code I use:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import library from './FontAwesomeLibrary';
import logo from '../../assets/images/logo.svg';
import {
Collapse,
Navbar,
NavbarToggler,
Nav,
NavItem } from 'reactstrap';
class Topbar extends Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.closeNavbar = this.closeNavbar.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
this.state = {
isOpen: false,
};
}
componentWillMount() {
document.addEventListener('mousedown', this.handleClickOutside);
}
componentWillUnmount() {
document.removeEventListener('mousedown', this.handleClickOutside);
}
toggle() {
this.setState({
isOpen: !this.state.isOpen
});
}
closeNavbar() {
this.setState({
isOpen: false
});
}
handleClickOutside(event) {
const t = event.target;
if (this.state.isOpen && !t.classList.contains('navbar-toggler')) {
this.closeNavbar();
}
}
render() {
return (
<div className="topbar">
<section className="container">
<Navbar color="light" className="header" expand="md">
<Link className="locoLink" to="/"><img src={logo} className="logo" alt="logo" /></Link>
<Link to="/" className="logoCompany">Redux Blog</Link>
<NavbarToggler onClick={this.toggle}>
<FontAwesomeIcon icon={this.state.isOpen ? "times" : "bars"}/>
</NavbarToggler>
<Collapse isOpen={this.state.isOpen} navbar>
<Nav className="ml-auto routes" navbar>
<NavItem>
<Link to="/" onClick={this.closeNavbar}>Posts</Link>
</NavItem>
<NavItem>
<Link to="/posts/new" onClick={this.closeNavbar}>New Post</Link>
</NavItem>
</Nav>
</Collapse>
</Navbar>
</section>
</div>
);
}
}
export default Topbar;
It also handles outside clicks.
FontAwesomeLibrary
import { library } from '#fortawesome/fontawesome-svg-core';
import { faCoffee } from '#fortawesome/free-solid-svg-icons';
import { faMugHot } from '#fortawesome/free-solid-svg-icons';
import { faTimes } from '#fortawesome/free-solid-svg-icons';
import { faBars } from '#fortawesome/free-solid-svg-icons';
import { faChevronUp } from '#fortawesome/free-solid-svg-icons';
library.add(faCoffee);
library.add(faMugHot);
library.add(faTimes);
library.add(faBars);
library.add(faChevronUp);
export default library;
I created FontAwesomeLibrary according to
https://fontawesome.com/how-to-use/on-the-web/using-with/react
This is an issue with routing. On a normal webpage a link in a bootstrap nav would cause a new page to load with the nav now closed. Since react doesn't reload the page the nav remains open. In order to fix this you'll need to add the following to each of your <Link> elements in the nav: onClick={this.toggleNavbar}.

React CSSTransitionGroup with multiple components

I am trying to build a reusable animated overlay.
However, only the first component mount is detected, meaning that I can only use this overlay once for my whole application. If I use a second one, it won't be animated.
I tried a lot of thing, like using unique keys, transition names and so on, but I can't get this to work.
Here is the current code:
import React from 'react';
import { CSSTransitionGroup } from 'react-transition-group';
import styled from 'styled-componets'
const OverlayDiv = styled.div`
transition: opacity 300ms ease-in;
&._overlay-transition-appear,
&._overlay-transition-enter {
opacity: 0.01;
}
&._overlay-transition-appear._loading-overlay-transition-appear-active,
&._overlay-transition-enter._loading-overlay-transition-enter-active {
opacity: 1;
}
&._overlay-transition-leave {
opacity: 1;
}
&._overlay-transition-leave._loading-overlay-transition-leave-active {
opacity: 0;
}
`;
const animated = (WrappedComponent) => ({ animate = true, ...otherProps }) => {
if (animate) {
return (
<CSSTransitionGroup
transitionName="_overlay-transition"
transitionAppear
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
transitionAppearTimeout={500}
>
<WrappedComponent {...otherProps} />
</CSSTransitionGroup>
);
}
return <WrappedComponent {...otherProps} />;
};
export const Overlay = ({ animate = true, className, parentDimensions, children }) => (
<OverlayDiv
key="overlay" // import for React CSS Transition
className={className}
height={parentDimensions ? `${parentDimensions.offsetHeight}px` : '100%'}
>
{children}
</OverlayDiv>
);
export default animated(Overlay);
Any idea on this ?

Resources