Managing state when changing backgroundImage - reactjs

In state I'm setting background image with a photo and I wanted to do 2 buttons, one is changing background image to another photo and another is setting background image back to the first photo.
Here is piece of my code:
\\index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import "semantic-ui/dist/semantic.min.css";
import logo1 from "./modules/images/one.jpg";
ReactDOM.render(
<App bgImage={`url(${logo1})`} />,
document.getElementById("root")
);
\\App.js
import React, { Component } from "react";
import "./App.css";
import NavBar from "./modules/NavBar";
import logo1 from "./modules/images/one.jpg";
import logo2 from "./modules/images/night.jpg";
class App extends Component {
constructor(props) {
super(props);
this.state = {
bgImage: props.bgImage //so here I set the backroundImage with logo1, because I want to logo1 to be on the start of application, but when I change to logo2 I want to have that logo2 even when I refresh page ( but when I do it, constructor of App is setting it to the logo1. So maybe, can I save that logo even when the App is reloading to get the latest logo ?
};
}
ChangeToLightMode = e => {
this.setState({
bgImage: `url(${logo1})`
});
};
ChangeToDarkMode = e => {
this.setState({
bgImage: `url(${logo2})`
});
};
render() {
return (
<div
style={{
display: "flex",
minHeight: "100vh",
flexDirection: "column",
backgroundImage: this.state.bgImage,
height: "100%",
width: "100%"
}}
>
<NavBar
ChangeToDarkMode={this.ChangeToDarkMode}
ChangeToLightMode={this.ChangeToLightMode}
/>
);
}
}
export default App;
\\NavBar.js
import React, { Component } from "react";
class NavBar extends Component {
render() {
return (
<div>
<Menu fixed="top" inverted>
<Menu.Menu position="right">
<Menu.Item onClick={this.props.ChangeToDarkMode}>
DarkMode
</Menu.Item>
<Menu.Item onClick={this.props.ChangeToLightMode}>
LightMode
</Menu.Item>
</Menu.Menu>
</Menu>
</div>
);
}
}
So I implemented a way that I can change background photo but when I click for example logo in my application and the constructor of App is called it is setting my bgImage to the first photo even when I had second photo and I know it. But I want only the first photo to be set in constructor in the start of the application, after it I want to have the photo according to which method I use. So should I store somewhere the bgImage state and do something with it in App constructor ?

If the default value for bgImage needs to be determined before App is rendered, then usually you would do this by passing a prop into the component e.g.
<App bgImage={`url(${logo1})`} />
Then in the constructor, you can set this as the default state
class App extends Component {
constructor(props) {
super(props);
this.state = {
bgImage: props.bgImage
};
}
}

Related

In react how do I get a modal to display in one component by clicking an icon in another?

I am using material UI with React. I have a modal component and a ButtonAppBar. Inside the ButtonAppBar there is a shopping cart icon that I added. I am still a bit new to React and would like to know the best way to display the modal when the shopping cart is clicked. Thanks in advance.
So here is my App.js:
import React, { Component } from 'react';
import { BrowserRouter } from 'react-router-dom';
import { Route } from 'react-router-dom';
import './App.css';
import ShopHome from './containers/ShopHome';
import ButtonAppBar from './components/ButtonAppBar';
import SimpleModalWrapped from './containers/ShoppingCartModal';
class App extends Component {
handle
render() {
return (
<BrowserRouter>
<div>
<ButtonAppBar />
<SimpleModalWrapped />
<Route exact path="/" component={ShopHome} />
</div>
</BrowserRouter>
);
}
}
export default App;
Here is my ButtonAppBar:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
import SvgIcon from '#material-ui/core/SvgIcon';
import ShoppingCart from '#material-ui/icons/ShoppingCart';
const styles = {
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
appBar: {
marginBottom: 50,
}
};
function ButtonAppBar(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar style={styles.appBar} position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" className={classes.grow}>
Velo-Velo
</Typography>
<Button color="inherit">Checkout</Button>
<SvgIcon>
<ShoppingCart />
</SvgIcon>
</Toolbar>
</AppBar>
</div>
);
}
ButtonAppBar.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ButtonAppBar);
Here is the modal:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import Typography from '#material-ui/core/Typography';
import Modal from '#material-ui/core/Modal';
import Button from '#material-ui/core/Button';
function rand() {
return Math.round(Math.random() * 20) - 10;
}
function getModalStyle() {
const top = 50 + rand();
const left = 50 + rand();
return {
top: `${top}%`,
left: `${left}%`,
transform: `translate(-${top}%, -${left}%)`,
};
}
const styles = theme => ({
paper: {
position: 'absolute',
width: theme.spacing.unit * 50,
backgroundColor: theme.palette.background.paper,
boxShadow: theme.shadows[5],
padding: theme.spacing.unit * 4,
},
});
class SimpleModal extends React.Component {
state = {
open: false,
};
handleOpen = () => {
console.log('clicked')
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
render() {
const { classes } = this.props;
return (
<div>
{/* <Typography gutterBottom>Click to get the full Modal experience!</Typography>
<Button onClick={this.handleOpen}>Open Modal</Button> */}
<Modal
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={this.state.open}
onClose={this.handleClose}
>
<div style={getModalStyle()} className={classes.paper}>
<Typography variant="h6" id="modal-title">
Text in a modal
</Typography>
<Typography variant="subtitle1" id="simple-modal-description">
Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
</Typography>
<SimpleModalWrapped />
</div>
</Modal>
</div>
);
}
}
SimpleModal.propTypes = {
classes: PropTypes.object.isRequired,
};
// We need an intermediary variable for handling the recursive nesting.
const SimpleModalWrapped = withStyles(styles)(SimpleModal);
export default SimpleModalWrapped;
Your best bet is to use something like Redux. As a lazier strategy have a Higher Order Component house both components. The higher order component can have the function which needs to run when you click on the icon and it changes something in the state of the higher order Component.
Say you have:
import React, { Component } from 'react'
import ComponentWithIcon from './icon-holder'
import ModalComponent from './modal'
class OuterContainer extends Component {
state = { modalOpen: false }
setModal = openOrClose => this.setState({modalOpen: openOrClose})
render(){
const {setModal, state: { modalOpen } } = this
return (
<>
<ComponentWithIcon
handleModalClick={setModal}
/>
<ModalComponent
isOpen={modalOpen}
handleModalClick={setModal}
/>
</>
)
}
}
As a result rather than the Modal component determining whether it is open (having it in its own state) which means that only it will know about whether it is presently open that will be determined by the OuterContainer... The OuterContainer is also the one which will handleTheClickEvent which clicking on the icon causes, so instead of running its own function, the icon will run the OuterComponent's function to setState...
This functionality (the clickHandler) and the state is passed to each of those child components through their props. Since the modal needs to be able to close that too can be passed in from the OuterComponent and it can be kept with the same state.modalOpen and possibly the same passed in action (clickHandler) which is toggle (or if you need for some reason then you can have an openModal/closeModal defined by the OuterComponent and pass both of those callbacks to be run by the modal.
Using redux (with react-redux) you have a single <Provider> component which is the higher order components to all of its children. The provider keeps in state a general store which is generated through redux's createStore() this store then gets actions which manipulate the central store and because it is at the top level it is able to inject its current state (or specific parts of it) to any component that is held within the Provider (which is every single component). Each of those components are able to send messages to that provider using dispatch() they then dispatch actions to the store and that results in the store being replaced with a new store that has things updated inside of it (such as whether the modal is open).
import React from 'react'
const MyModal = ({isOpen, handleModal }) => (
<div className={`modal ${isOpen ? 'is-showing' : 'is-hidden'}`}>
<div
className='toolbar'
>
<CloseButton onClick={() => handleModal(false)} />
</div>
<div>
{/* Modal content */}
</div>
</>
)

How to control size of my webview in electron react

I have started a brand new project build on some basic react/electron boilerplate code. I downloaded https://www.npmjs.com/package/react-electron-web-view as a wrapper to make sure i could use electrons webview within react, but I am not able to control the size, always looks like this:
This is the code
import '../assets/css/App.css';
import React, { Component } from 'react';
class App extends React.Component {
render() {
const WebView = require('react-electron-web-view');
return (
<div styles={{float : 'left', paddingRight : '5px', height :
'5px'}}>
<webview id="foo" src="https://www.github.com/" height = "5px" />
</div>
);
}
}
export default App;

React - Inline CSS and Image won't load

I'm still new to React and after I finished the tutorial I wanted to create something myself.
I've passed the url to make a backgroundImage style and add borders to try it out. Unfortunately I can see the img being set in the css but it won't actually display as expected.
As a test I also tried a simple img with src attribute set to my image and nothing would display.
I made a folder called img inside the src
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<Home/>
</div>
);
}
}
function Portfolio(props) {
const stylee = {
backgroundImage:'url('+props.imgURL+')',
borderWidth: 1,
};
const ide = 'portfolio'+props.counting;
return (<div id={ide} style={stylee} className='portfolio'/>)
}
class Home extends Component {
renderPortfolio(count,img){
return <Portfolio counting={count} imgURL={img}/>
}
render(){
return(
<div>
{this.renderPortfolio(1,'./img/1.jpeg')}
{this.renderPortfolio(2,'./img/2.jpeg')}
{this.renderPortfolio(3,'./img/1.jpeg')}
<img src='./img/1.jpeg'/>
</div>
)
}
}
export default App;
What am I doing wrong that is preventing the images from displaying ?
edit-- I've changed my code to the working solution
Instead of passing the local img url, I used require() first then pass the image to props.
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<Home/>
</div>
);
}
}
function Portfolio(props) {
const counter = 'portfolio'+props.counting;
const loadGambar = props.gmbr;
// const loadGambar2 = require(props.gmbr);
const stylee = {
borderColor:props.color,
border:1,
borderWidth: 10,
backgroundImage: "url("+loadGambar+")",
}
return(
<div id={counter} className='portfolio' style={stylee}>
</div>
)
}
class Home extends Component {
renderPortfolio(count,gambare){
return <Portfolio counting={count} gmbr={gambare}/>
}
render(){
return(
<div>
{this.renderPortfolio(1,require('./img/1.jpg))}
{this.renderPortfolio(2,require('./img/1.jpg'))}
{this.renderPortfolio(3,require('./img/2.jpg'))}
</div>
)
}
}
export default App;
Here's a link to a working example based on your code: sandbox link.
The problem with setting a background image is that it adapts to the dimensions of the div. In your case your div is empty in Portfolio so its dimensions are 0x0 and the image won't show. You will see from the link that I update the style and everything shows. Now the only issue you might have is that you don't have an image loader in your webpack configuration, if you are starting with react I would recommend create-react-app.

Not able to Render components in react Native

I want to make a chat app in react native and Currently I am designing static chat screen which should look like this.
So what I am doing to make this kind of chat screen is I am making two seperate components Message Sender and Message Reciever
This is my MessageReciever Component
import React, { Component } from 'react';
import { Container, Header, Content, Button, Text, Icon } from 'native-base';
import { StyleSheet } from 'react-native';
class MessageReciever extends Component {
render() {
return (
<Container>
<Content>
<Button style ={{marginLeft:22,marginTop:28,backgroundColor:'#F0F0F0',borderRadius:12,
flexDirection:'column',height:'auto',width:280,alignItems:'stretch',flex:1,}} disabled>
<Text style ={styles.nameText}>Jordan</Text>
<Button transparent style ={{backgroundColor:'#F0F0F0',
height:'auto',width:280,alignItems:'stretch',borderRadius:12,flex:1}} disabled>
<Text uppercase = {false} style ={styles.messageText} >Epo polam valayada?
</Text>
<Text style ={styles.timeText}>08:23AM</Text>
</Button>
</Button>
</Content>
</Container>
);
}
}
const styles = StyleSheet.create({
timeText:{
fontSize:14,
textAlign:'right',
opacity:0.50,
color:'#000000'
},
messageText:{
fontSize:17,
textAlign:'left',
opacity:1.0,
width:200,
height:'auto',
color:'#000000',
alignItems:'stretch',
},
nameText:{
fontSize:15,
textAlign:'left',
opacity:1.0,
width:200,
height:'auto',
color:'green',
alignItems:'stretch',
},
})
export default MessageReciever;
and This is my MessageSender Component
import React, { Component } from 'react';
import { Container, Header, Content, Button, Text, Icon } from 'native-base';
import { StyleSheet } from 'react-native';
class MessageSender extends Component {
render() {
return (
<Container>
<Content>
<Button style ={{backgroundColor:'#3399ff',
marginLeft:67,marginTop:28,borderRadius:12,
height:'auto',width:287,alignItems:'stretch',flex:1}} disabled>
<Text uppercase = {false} style ={styles.messageText}>Players differentiation missing.
Notification for our own message?
</Text>
<Text style ={styles.timeText}>08:23AM</Text>
</Button>
</Content>
</Container>
);
}
}
const styles = StyleSheet.create({
timeText:{
fontSize:14,
textAlign:'right',
opacity:0.50,
color:'#FFFFFF'
},
messageText:{
fontSize:17,
opacity:1.0,
width:210,
height:'auto',
color:'#FFFFFF',
alignItems:'stretch',
},
nameText:{
fontSize:15,
textAlign:'left',
opacity:1.0,
width:200,
height:'auto',
color:'green',
alignItems:'stretch',
},
})
export default MessageSender;
And this is my main Chat Screen where I am calling these two components in the render method
import React, { Component } from 'react';
import { Container, Header, Content, Button, Text, Icon } from 'native-base';
import { StyleSheet } from 'react-native';
import { MessageReciever } from '../components/MessageReciever';
import { MessageSender } from '../components/MessageSender';
import { Separator , SeparatorDate } from '../components/List';
class ChatMessageScreen extends Component {
render() {
return (
<Container>
<Header/>
<Content>
<MessageReciever />
<MessageSender />
</Content>
</Container>
);
}
}
export default ChatMessageScreen;
The problem I am facing is when I am calling these two components in the render method only one component is rendered either MessageReciever or MessageSender which is called first.
I am not able to understand the problem so Please have a look at and help me.
I have noticed my mistake actually in the render function of components I am wrapping the content inside the container so it is taking whole screen space so when I am calling these components inside my screen it is rendering that component but each rendered with the space of whole screen in between two components. So just removed container from the components and everything is working fine.

React native not overlapping statusbar

Im learing React native but i dont understand how to get everything to not overlap with the status bar.
I have tried
translucent={true/flase}
hidden
This is expected behaviour, one solution is to add a padding to your top level view equal to current height of status bar or have a StatusBarView that has same height as the status bar.
Refer to this plugin https://github.com/jgkim/react-native-status-bar-size for listening to status bar height changes.
For e.g
import _ from 'lodash';
import React, { Component } from 'react';
import { View, StatusBar} from 'react-native';
import StatusBarSizeIOS from 'react-native-status-bar-size';
const STATUS_BAR_EXTRA_PADDING = 2;
const DEFAULT_STATUS_BAR_HEIGHT = 10;
class StatusBarView extends Component {
state = {
statusBarHeight: _.get(StatusBarSizeIOS, 'currentHeight', DEFAULT_STATUS_BAR_HEIGHT);
}
_handleStatusBarSizeDidChange = (statusBarHeight) => this.setState({ statusBarHeight })
componentDidMount() {
StatusBarSizeIOS.addEventListener('didChange', this._handleStatusBarSizeDidChange);
}
render() {
return (
<View
style={{
height: this.state.statusBarHeight + STATUS_BAR_EXTRA_PADDING,
}}
>
<StatusBar {...this.props} />
</View>
);
}
}
export default StatusBarView;
Now inside your screens you could do something like
import StatusBarView from '{view_path}';
...
render() {
return (
<View>
<StatusBarView barStyle="default" />
<View>{rest of the view}</View>
</View>
);
}

Resources