I would like to understand how to dynamically change the position of a component (iframe) for each change of state. I have three different iframes, which I want to render at three different times, and in three different positions. I can't understand if it is possible to enter the coordinates of the positions I want in the state, or there is another way to do this.
I insert the part of the code concerned, for an easier understanding.
import React, { Component } from "react";
class Pubblicita extends Component {
state = {
index: 0,
iframeSrcs: ["/300x250", "/160x600", "/468x60"],
heightSrcs: [250, 600, 60],
widthSrcs: [300, 160, 468],
visibility: false
};
render() {
return (
<div>
<button style={{ opacity: "0" }} onClick={this.reload}>
pubblicitĂ
</button>
{this.state.visibility ? (
<iframe
key={this.state.index}
title="AdSlot"
src={this.state.iframeSrcs[this.state.index]}
height={this.state.heightSrcs[this.state.index]}
width={this.state.widthSrcs[this.state.index]}
scrolling="no"
frameborder="0"
allowFullScreen="true"
/>
) : (
""
)}
</div>
);
}
}
export default Pubblicita;
Thank you all in advance.
Related
I'm trying to recreate the effect shown at https://hexed.it/
When you hover over either list the corresponding byte in the other list is also highlighted. I figured a panel with each list inside it that had a state with the current hovered byte would do but it seems that React wants to re-render the entire list or do something strange every time resulting in larger files being unbearably slow.
I see a lot of "use memo! use the useCallback hook!" when searching and I've tried... it's still slow and I'm not sure why. It seems like it's only rendering the updated HexByte but it's still unacceptably slow for large files.
Sandbox: https://codesandbox.io/s/flamboyant-ellis-btfk5s
Can someone help me quicken/smooth out the hovering?
I solved it using this answer: Prevent DOM element re-render in virtualized tree component using react-window
In short the things I've learned:
memo has no effect if a component has a useState in it
Large lists of data should be rendered using a library like react-window
The cell rendering function as mentioned in the answer above can't be part of a parent component
As an example for anyone coming here, the new HexPanel class looks like so
import Box from '#mui/material/Box';
import { memo } from 'react';
import { FixedSizeGrid as Grid, areEqual } from 'react-window';
const HexByte = memo(function HexByte(props) {
const onMouseEnter = () => {
props.onHover(props.index);
//setInside(true);
}
const onMouseLeave = () => {
//setInside(false);
}
const onClick = () => {
//setClicked(true);
}
return (
<span
style={{
display: 'inline-block',
padding: '5px',
backgroundColor: props.hoverIndex == props.index ? '#777' : 'transparent',
color: 'darkblue'
}}
onClick={onClick}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
{props.byte}
</span>
)
}, (prevProps, nextProps) => nextProps.hoverIndex != nextProps.index);
const Cell = memo(function({ data, columnIndex, rowIndex, style }) {
return (
<div style={style}>
<HexByte byte={data.hex[rowIndex][columnIndex]} onHover={data.onHover} hoverIndex={data.hoverIndex} index={`${rowIndex}${columnIndex}`} />
</div>
)
}, areEqual);
const HexPanel = (props) => {
return (
<Box
sx={{
fontFamily: 'Source Code Pro',
display: 'flex',
flexDirection: 'column',
}}
>
<Grid
columnCount={16}
columnWidth={30}
height={900}
itemData={props}
rowCount={props.hex.length}
rowHeight={35}
width={500}
>
{Cell}
</Grid>
</Box>
)
}
export default HexPanel;
I need to solve a question that is asking to change the body background colours while clicking the button I need to change four colours how I can solve it? in react.
import React, { useState } from 'react';
import './App.css';
function App() {
var colors=[
{
value:1,label:"red"
},
{
value:2,label:"green"
}
]
var [setbgcolor,ddlvalue]=useState(colors.label)
var ddlhandle=e=>{
ddlvalue(e.label)
}
return (
<div className="App">
<style>{'body {background-color:'+setbgcolor+'}'}</style>
<button onClick={ddlhandle} >click</button>
<select options={colors} onChange={ddlhandle}></select>
</div>
);
}
export default App;
You would need two states, one for holding the select's value, and other for holding current bg color. Similarly, you need two handlers, one for select and other for button. Also, you need to use option element, inside select to display the options.
import React, { useState } from "react";
import "./styles.css";
export default function App() {
var colors = [
{
value: 1,
label: "red"
},
{
value: 2,
label: "green"
}
];
var [inputValue, setInputValue] = useState(colors[0].label);
var [bgcolor, setbgColor] = useState(colors[0].label);
var ddlhandle = (e) => {
setInputValue(e.target.value);
};
var buttonHandle = () => {
setbgColor(inputValue);
};
return (
<div
style={{ backgroundColor: bgcolor, width: "100vw", height: "100vh" }}
className="App"
>
<button onClick={buttonHandle}>click</button>
<select onChange={ddlhandle}>
{colors.map((color) => (
<option value={color.label}>{color.label}</option>
))}
</select>
</div>
);
}
CodeSandbox Link - https://codesandbox.io/s/zealous-williamson-58qf8?file=/src/App.js
Edit: Since you need to change the color of entire body, you need to set width: "100vw" and height: "100vh" of div.
you should use two className or two style for the background
and handle a parameter for change between className or style
import React, { useState } from 'react';
import './App.css';
function App() {
var colors=[
{
value:1,label:"red"
},
{
value:2,label:"green"
}
]
var [setbgcolor,ddlvalue]=useState(colors[0].label)
var ddlhandle=e=>{
ddlvalue(e.target.value)
}
return (
**<div className="App" style={{backgroundColor:`${setbgcolor}`}}>**
<button onClick={ddlhandle} >click</button>
<select options={colors} onChange={ddlhandle}></select>
</div>
);
}
export default App;
If you want with a single click of a button to cicle thru an array of possible colors to change the background color, you can simply store the array index of the current one and +1 to it until you reach the limit then reset back to 0.
Heres a short example:
Created an array with objects that represent what colors can be picked
const colors = [
{ title: "Red", color: "#de1212" },
{ title: "Blue", color: "#122dde" },
{ title: "Green", color: "#32a852" },
{ title: "Yellow", color: "#d7de12" }
];
Then created a state where you can store the index of the current selected color. NOTE giving a default index of 0
const [colorValue, setColorValue] = useState(0);
Then simply, create a simple method that onClick will execute. This method will increate the index by 1 until it reaches same number as there are objects in the array. Once reached the limit it will reset it to 0
const handleClick = () =>
setColorValue(colorValue + 1 < colors.length ? colorValue + 1 : 0);
Now in a render its up to you how you render it. I simply did this to present it
<div className="App" style={{ backgroundColor: colors[colorValue].color }}>
<h1>Selected color: {colors[colorValue].title}</h1>
<button className="btn" onClick={handleClick}>
Click to change color
</button>
</div>
Live example of this code
And if you required to do this with a select and only with a button onClick to read select value and set it as color, the situation is the same just add 1 more state where you seperatly store select value OR use a ref. The rest is the same.
Also, as a note, do not use var. Its so old. Use let, for variables that values change, and const, for variables whos value do not change.
What I am trying to do:
I am trying to implement a "customizable" chessboard using chessboardjsx in a ReactJS application with the option to change pieces style. Basically I am trying to dynamically change the src attribute of an <img> tag. To do that, in the example below, I click a button that change a prop that ideally should change the pieces icons.
Where is the problem: My problem is that even if prop is updated, src doesn't get updated.
What I tried and what I've read on SO: firstly I thought it might be a problem of browser caching (I've read on SO a lot of question about this problem) but even implementing solution like disabling the cache, adding a key to the img tag or adding an hash to src didn't solve the problem. Therefore I tried to substitute the img tag with a p and writing the variable inside: prop actually did not changed, the value is always the first value assigned.
Expected Behavior: When I click the button, the images of the kings get swapped. (Again, this is an example, but the mechanism is the same). Here an image of the chessboard:
Below I present a simplified version of my code to make it more understandable.
import React, { useEffect, useState } from "react";
import Chessboard from "chessboardjsx";
import elvis from "../img/elvis.png";
import lebronJames from "../img/kingJames.png";
import { roughSquare } from "../customRough";
/* eslint react/display-name: 0 */
/* eslint react/prop-types: 0 */
export default function CustomizedBoard(props) {
const [pieces, setPieces] = useState(props.pieces);
useEffect(() => {
setPieces(props.pieces);
}, [props.pieces]);
return (
<Chessboard
id="standard"
orientation="black"
width={320}
roughSquare={roughSquare}
position="start"
boardStyle={{
borderRadius: "5px",
boxShadow: `0 5px 15px rgba(0, 0, 0, 0.5)`
}}
dropOffBoard="trash"
pieces={{
wK: ({ squareWidth, isDragging }) => (
<img
style={{
width: isDragging ? squareWidth * 1.75 : squareWidth,
height: isDragging ? squareWidth * 1.75 : squareWidth
}}
src={pieces === "a" ? elvis : lebronJames}
alt={"elvis"}
/>
),
bK: ({ squareWidth, isDragging }) => (
<img
style={{
width: isDragging ? squareWidth * 1.75 : squareWidth,
height: isDragging ? squareWidth * 1.75 : squareWidth
}}
src={pieces === "a" ? lebronJames : elvis}
alt={"lebron james"}
/>
)
}}
sparePieces={false}
lightSquareStyle={{ backgroundColor: "AliceBlue" }}
darkSquareStyle={{ backgroundColor: "CornFlowerBlue" }}
/>
);
}
After reading several question on what I thought might be the problem, without any success, I thing I am not on the right path. So, what could be a solution? Or what could be the problem I come across?
Thank you in advance.
EDIT
Here's the code from which I change the prop of Chessboard.
class Demo extends Component {
state = {
pieces: "a"
};
render() {
return (
<div style={boardsContainer}>
<button
onClick={() => {
this.setState({ pieces: this.state.pieces === "a" ? "b" : "a" });
}}
>
Change Theme
</button>
<CustomBoard pieces={this.state.pieces} />
</div>
);
}
}
export default Demo;
This question is related to this post:
React Router v4 Match transitions using React Motion
...but I thought it deserved its own question.
I'm trying to figure out how to use the <MatchWithFade> example taken from here:
https://react-router.now.sh/animated-transitions
The problem I'm seeing is that if I have two tabs, and I want to fade between them, I'm only seeing the fade effect on one of the two tabs, and it depends on which <MatchWithFade> appears first in my code.
The relevant code is as follows:
const One = () => {
return (
<div style={{position:'absolute', top: 0, left: 0, width: 300, backgroundColor: 'orange'}}>
One one one one one one one one one one
</div>
)
}
const Two = () => {
return (
<div style={{position:'absolute', top: 0, left: 0, width: 300, backgroundColor: 'yellow'}}>
Two two two two two two two two two two
</div>
)
}
class AppBody extends Component {
render () {
return (
<div style={{position: 'relative'}}>
<MatchWithFade pattern='/one' component={One} />
<MatchWithFade pattern='/two' component={Two} />
</div>
)
}
}
In this example, navigating to /one, (using the React Router <Link> component) will cause the fade to happen, but if I navigate to /two, there is no fade. Then, if I list <MatchWithFade pattern='/two' ... /> first, then I see the fade transition to /two, but not /one.
Just using <Match> works fine, so I don't think it's a fundamental issue with how I have <BrowserRouter> configured.
I'm hoping that I'm just doing something silly, but for the life of me, I can't figure out what. Any guidance is appreciated.
UPDATE
I couldn't figure out how to made a jsbin using React Router (couldn't figure out how to reference the methods and objects on it, since I've only ever used RR via import statements). So here's the next best thing: this is a complete example that demonstrates this issue:
import React, { Component } from 'react';
import BrowserRouter from 'react-router/BrowserRouter'
import { TransitionMotion, spring } from 'react-motion'
import Match from 'react-router/Match'
import Link from 'react-router/Link';
const MatchWithFade = ({ component:Component, ...rest }) => {
const willLeave = () => ({ opacity: spring(0) })
return (
<Match {...rest} children={({ matched, ...props }) => {
return (
<TransitionMotion
willLeave={willLeave}
styles={matched ? [ {
key: props.location.pathname,
style: { opacity: 1 },
data: props
} ] : []}
>
{interpolatedStyles => {
return (
<div>
{interpolatedStyles.map(config => (
<div
key={config.key}
style={{...config.style }}
>
<Component {...config.data}/>
</div>
))}
</div>
)
}}
</TransitionMotion>
)
}}/>
)
}
const One = () => {
return (
<div style={{position:'absolute', top: 0, left: 0, width: 300, border: '1px solid black', backgroundColor: 'orange', minHeight: 200}}>
One one one one one one one one one one<br />
One one one one one one one one one one<br />
</div>
)
}
const Two = () => {
return (
<div style={{position:'absolute', top: 0, left: 0, width: 300, border: '1px solid black', backgroundColor: 'yellow', minHeight: 200}}>
Two two two two two two two two two two<br />
Two two two two two two two two two two<br />
</div>
)
}
class App extends Component {
render () {
return (
<BrowserRouter>
<div style={{padding: 12}}>
<div style={{marginBottom: 12}}>
<Link to='/one'>One</Link> || <Link to='/two'>Two</Link>
</div>
<div style={{position: 'relative'}}>
<MatchWithFade pattern='/one' component={One} />
<MatchWithFade pattern='/two' component={Two} />
</div>
</div>
</BrowserRouter>
)
}
}
export default App;
There are only very minor differences between this MatchWithFade, and the one taken from the React Router docs. The biggest difference is that I pulled out the zIndex reference, but that did not affect the behavior.
If it's relevant, I started this project using create-react-app, and I'm using React Router version 4.0.0-alpha.6.
This is an issue with the style you're applying (or not) from the MatchWithFade example. Add zIndex: 1 back to your willLeave function, as this ensures the outgoing route is over top of the incoming in order to see the opacity fade.
Then add the absolute positioning back to the wrapper div you're applying the style to (styles.fill in the website example) so that they can overlap each other.
Here is a gist with your code fixed up.
This question is a follow-up to this:
Trouble with React Router v4 and MatchWithFade
I've got another (potentially silly) question about using MatchWithFade and React Router v4. What I'd like to do is have nested routes, so a top-level component might have this:
<MatchWithFade pattern='/one' component={One} />
...and then One might have this:
<Match pattern='/one/one' Component={OneOne} />
This doesn't strike me as an unusual pattern (though maybe it is). In any event, the behavior I'm observing is that, using the above example, if I load OneOne, it gets mounted, and then componentWillUnmount is immediately called. Had I to guess, I'd say that TransitionMotion is keeping track of a (perhaps hidden) instance of OneOne, and once the transition is complete, it unmounts that hidden component. As far as the basic UI is concerned, OneOne is rendered. However, if componentWillUnmount does any cleanup (like, say, removing something from Redux), then of course that action is fired, and any data tied to OneOne is blown away.
Here's a complete example that illustrates the problem:
import React, { Component } from 'react';
import BrowserRouter from 'react-router/BrowserRouter'
import { TransitionMotion, spring } from 'react-motion'
import Match from 'react-router/Match'
import Link from 'react-router/Link';
const styles = {
fill: { position: 'absolute', top: 0, left: 0 }
};
const MatchWithFade = ({ component:Component, ...rest }) => {
const willLeave = () => ({ zIndex: 1, opacity: spring(0) })
return (
<Match {...rest} children={({ matched, ...props }) => {
return (
<TransitionMotion
willLeave={willLeave}
styles={matched ? [ {
key: props.location.pathname,
style: { opacity: 1 },
data: props
} ] : []}
>
{interpolatedStyles => {
return (
<div>
{interpolatedStyles.map(config => (
<div
key={config.key}
style={{...styles.fill, ...config.style }}>
<Component {...config.data}/>
</div>
))}
</div>
)
}}
</TransitionMotion>
)
}}/>
)
}
const TwoOne = () => {
return (
<div>Two One</div>
)
}
class TwoTwo extends Component {
componentWillUnmount() {
console.log("TwoTwo will unmount")
}
render () {
return (
<div>Two Two</div>
)
}
}
const TwoHome = () => {
return (
<div>Two Home</div>
)
}
class One extends Component {
componentWillUnmount () {
console.log("ONE UNMOUNTING")
}
render () {
return (
<div style={{ width: 300, border: '1px solid black', backgroundColor: 'orange', minHeight: 200}}>
One one one one one one one one one one<br />
One one one one one one one one one one<br />
</div>
)
}
}
const Two = () => {
return (
<div style={{ width: 300, border: '1px solid black', backgroundColor: 'yellow', minHeight: 200}}>
<Match pattern='/two/one' component={TwoOne} />
<Match pattern='/two/two' component={TwoTwo} />
<Match pattern='/two(/)?' exactly={true} component={TwoHome} />
</div>
)
}
class App extends Component {
render () {
return (
<BrowserRouter>
<div style={{padding: 12}}>
<div style={{marginBottom: 12}}>
<Link to='/one'>One</Link> || <Link to='/two'>Two</Link>
|| <Link to='/two/one'>Two One</Link>
|| <Link to='/two/two'>Two Two</Link>
</div>
<div style={{position: 'relative'}}>
<MatchWithFade pattern='/one' component={One} />
<MatchWithFade pattern='/two' component={Two} />
</div>
</div>
</BrowserRouter>
)
}
}
export default App;
If you load this and open a console, toggle between the One and Two links. You'll see the cross fade happen in the UI, and you'll see "ONE UNMOUNTING" in the console when the transition from One to Two completes. So that's right.
Now, click between Two One and Two Two. In this case, when Two One is clicked, you'll immediately see "TwoTwo will unmount" in the console, which is good. However, if you click Two Two, you'll see "TwoTwo will unmount" after about a second--which I take to be the amount of time the parent MatchWithFade takes to execute.
So I'm not sure what's going on here. Is my code just busted? Am I doing something that RRv4 cannot support? Have I uncovered a bug?
Any help/guidance is appreciated!
Your issue is your use of props.location.pathname as a key. This should always be the same for a component, but the way that you have written it, it changes each time that you navigate. Try changing this:
const styles = {
fill: { position: 'absolute', top: 0, left: 0 }
};
to:
const styles = {
fill: { position: 'relative', top: 0, left: 0 }
};
and you will see that you are rendering two instances of <Two> (one for each key).
If you were to use a constant key, such as rest.pattern (the pattern associated with this <Match>), your issue would go away.
styles={matched ? [ {
key: rest.pattern,
style: { opacity: 1 },
data: props
} ] : []}