How to add styles to a React component? [duplicate] - javascript

Currently I'm using react.js and I'm trying to get two div's to be side by side.
Currently I'm trying to
<div id="sidebar" style = "display:inline-block;" >
<script src="build/sidebar.js"></script>
</div>
<div id="map-canvas" style="display: inline-block; width: 20%; height: 50%; "></div>
with sidebar.js as the where react is stored. This unfortunately doesnt work however as it just moves map-canvas to the side while sidebar isn't to the left of it; its on top. I've tried many various combinations w/ float as well and none of them seem to work
Another option is to edit the sidebar.js code where I currently have
return <div>
<input type="text" value={this.state.searchString} onChange={this.handleChange} placeholder="Type here" />
<ul>
{ libraries.map(function(l){
return <li>{l.name} </li>
}) }
</ul>
</div>;
in which I try doing return <div style ="display: inline-block;">
However, in this case the generated html doesnt show up at all. I'm perplex to what I should try but react seems like it doesnt want to play nice with other div elements.

That's because in React, the style prop takes an object instead of a semicolon-separated string.
<div id="sidebar" style={{display : 'inline-block'}} >
<script src="build/sidebar.js"></script>
</div>
<div id="map-canvas" style={{display: 'inline-block', width: '20%', height: '50%'}}>
</div>
Edit:
So this:
return <div style="display: inline-block;">
Would become this:
return <div style={{display: 'inline-block'}}>

const styles = {
container: {
backgroundColor: '#ff9900',
...
...
textAlign: 'center'
}
}
export default class App extends React.Component {
render() {
return(
<div className="container" style={styles.container}>
// your other codes here...
</div>
);
}
}

Related

Styling the element in separate component using conditions in React

In my react app I have a hidden banner that I want to show, when the length of the array reaches to 5. But it looks like that I am trying to get an element before it is rendered. I get the error about getting a style of undefined element.
This function must change css of the banner element and make it visible.
showBanner() {
let banner = document.getElementsByClassName('overlay')[0]
banner.style.cssText = "visibility: visible;opacity: 1;"
}
I want to render my popup component only if the condition is met.
render() {
if (this.props.awarded) {
if (this.props.awarded.length === 5) {
this.showBanner()
return (
<>
<h1 id="awardLabel">5 movies</h1>
<div id="movieList">
{this.props.awarded.map((movie) => {
return (
<div className="awardHolder" key={movie.imdbID}>
<div className="awardImgHolder" >
<img src={movie.Poster} alt={movie.Title}></img>
</div>
<div className="awardMovieInfo">
<p>{movie.Title}</p>
<p>year {movie.Year}</p>
</div>
<div className="withdrawButton" onClick={(e) => this.deleteMovie(e, movie)}> WITHDRAW </div>
</div>
)
})}
</div>
<Popup />
</>
)
} else { ...
This is my banner structure.
<div id="popup1" className="overlay">
<div className="popup">
<h2>Here i am</h2>
<a className="close" href="#">×</a>
<div className="content">
<p>Congratulations. You've nominated 5 movies.</p>
<button onClick={this.closeBanner}>Try again</button>
</div>
</div>
</div>
This is my css for the banner element.
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
}
How can I dynamically change element's styles using conditions to render that element?
You're trying to access your Popup component before it gets created. In other words, this.showBanner() is called before <Popup /> is rendered.
One solution is to move your popup to a higher-level component
This might be a good use case for React Context, which will allow you to have some global state that your components can tap into without having to pass the banner state through multiple components as props.
If you are going to do this, you might consider not manually updating the styling with querySelectors; instead, you can have React either render or not render the component based on your global banner state.
Your application will be wrapped in <BannerContext.Provider> tags, and then the component that needs to render or not render the banner can use <BannerContext.Consumer> tags to check the current banner state. You can also store a toggle function in the BannerContext so that other parts of the application (and the banner itself) can toggle the BannerContext as needed.

use ref in reactjs-popup trigger

I have a react-table component with custom column header
const popupRef = createRef();
const column = [{
Header: () =>
<div ref={popupRef} className="eye-icon">
<img src={icon}/>
</div>
fixed: "left",
sortable: false,
headerClassName: "table-header-class",
className: "table-row-class",
width: 70
}];
And I have a reactjs-popup that I want to be triggered after I press on that component.
return (
<div>
<Popup
className="popup"
closeOnDocumentClick
trigger={popupRef.current}
arrow={true}
repositionOnResize={true}
on="click"
position="bottom left"
>
<div className="popup">
<span>popup</span>
</div>
</Popup>
<div className="table">
<ReactTableFixedColumns
showPagination={false}
defaultPageSize={selectedTestsLength}
data={data}
style={{height: "73vh"}}
columns={column}
/>
</div>
</div>
);
It doesn't work.
Of course I can make onClick event in header's div to forcly open the popup with reactjs-popup open property - but it appears on the center of the screen and it looks like modal, so this approach is not suitable, I want it to stick to the div, to be placed in correct place.
I think you are using the wrong approach here. Refs are not needed to achieve what you want.
Just simply declare the Popup inline inside the header:
const column = [{
Header: () =>
<Popup trigger={
<div ref={popupRef} className="eye-icon">
<img src={icon}/>
</div>
}>
<div className="popup">
<span>popup</span>
</div>
</Popup>
fixed: "left",
sortable: false,
headerClassName: "table-header-class",
className: "table-row-class",
width: 70
}];
I don't have access to your full code so I can't tell for sure but that should give you the idea.
I just did an empty div and put trigger in it
trigger={<div className="sample-trigger"></div>}
.sample-trigger {
width: 1px;
height: 1px;
display: block;
visibility: hidden;
}
In the main div I am using to trigger the popup I set the onClick to change the state of {wasPopupOpen}
<Popup
className="popup"
closeOnDocumentClick
open={wasEyePopupOpen}...
I also make some adjustmenst on popup window so it looks like inside of that div.

Unable to overlay component in React

I have the following modal component:
export default function LoginModal(props) {
const { showLogin, hideLogin } = props
if (!showLogin) return null
return (
<div class='overlay'>
<div class='modal'>
<article class='mw5 center bg-white br3 pa3 pa4-ns mv3 ba b--black-10'>
<div class='tc'>
<h1 class='f4'>Firstname Lastname</h1>
<hr class='mw3 bb bw1 b--black-10' />
</div>
<p class='lh-copy measure center f6 black-70'>
test test test test
</p>
</article>
</div>
</div>
)
}
which I am attempting to conditionally render using a state property stored in my redux store. However, when I place it as follows:
<article class='pv6 center ph3 ph5-ns tc br2 bg-washed-green dark-green mb5'>
PAGE CONTENT HERE
</article>
<LoginModal />
It appears below the rest of the screen content rather than above everything else as I had hoped. I am using the following css to try to get this effect, but it doesn't seem to be working:
.overlay {
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: 'rgba(0,0,0,0.3)';
padding: 50;
z-index: 300;
}
.modal {
background-color: '#fff';
border-radius: 5;
max-width: 500;
min-height: 300;
margin: '0 auto';
padding: 30;
}
I need the modal to appear as a login card in the center of the screen with the background dimmed, as is common on many websites. I would also rather not use a UI component library to achieve. Thanks for the help!
I think you are missing a position: fixed in your .overlay styles.
Also, you might want to consider using Portals to render the modal outside the DOM hierarchy of your App, that is, outside the <div id="app"></div> or <div id="root"></div> we commonly use.
To do that, your index.html or equivalent file would have something like this:
<div id="app"></div>
<div id="modal"></div>
And then you need to update your LoginModal like this:
export default function LoginModal(props) {
const { showLogin, hideLogin } = props;
if (!showLogin) return null;
return ReactDOM.createPortal((
<div class='overlay'>
<div class='modal'>
<article class='mw5 center bg-white br3 pa3 pa4-ns mv3 ba b--black-10'>
<div class='tc'>
<h1 class='f4'>Firstname Lastname</h1>
<hr class='mw3 bb bw1 b--black-10' />
</div>
<p class='lh-copy measure center f6 black-70'>
test test test test
</p>
</article>
</div>
</div>
), document.getElementById('modal'));
}
Note that if you try to reuse the code in this example to create a generic Modal component, you would only be able to show one at a time, as they would be rendering inside the same #modal element.
In the Portals documentation you can see an example that creates a new element dynamically so that you can have multiple modals at the same time.

set styling to div which contain TextInput field

I'm new to react and material ui. I'm using material ui version "1.0.0-beta.17" and react 15.6.2. Also has styled-components 2.0.0 and styled-components-breakpoint 1.0.1.
I have two TextInput fields in a div element.
const mycomponent = ({props}) => {
<div>
<SomeComponent />
<div>
<TextInput id="testId1" />
<TextInput id="testId2" />
</div>
</div>
}
Now when it render, it adds additional parent div to each input fields
Like this,
<div>
<div class="field--testId1">
<div class="FormItem__ElementWrapper-s14tem39-3 bgVlIQ">
<input id="testId1">
</div>
</div>
<div class="field--testId2">
<div class="FormItem__ElementWrapper-s14tem39-3 bgVlIQ">
<input id="testId2">
</div>
</div>
</div>
Now how can I target to the div to apply styles with class name field--testId1, field--testId2.
Here classname are generated by default material ui,
for example
.field--testId2{
width: "48%",
float: "left"
}
.field--testId2{
width: "48%",
float: "left"
}
I'm learning react and material ui so any help is much appreciated.
in order to override an existing class, you can add a styled-component wrapper instead of the wrapping div and override the child classes:
const TextInputWrapper = styled.div`
.field--testId2 {
// your custom styling
}
`
<TextInputWrapper>
<TextInput id="testId1" />
<TextInput id="testId2" />
</TextInputWrapper>
If you want to target div which has input, than you can follow these steps
Add a class to parent div, lets say wrapper
Target the closest div using > css selector
.wrapper > div {
border: 1px solid red;
width: 48%;
float: left;
margin-left: 1%;
}
input {
width: 100%;
box-sizing: border-box;
}
<div class="wrapper">
<div class="field--testId1">
<div class="FormItem__ElementWrapper-s14tem39-3 bgVlIQ">
<input id="testId1">
</div>
</div>
<div class="field--testId2">
<div class="FormItem__ElementWrapper-s14tem39-3 bgVlIQ">
<input id="testId2">
</div>
</div>
</div>
You give class directly to your textfield component and you can add your custom styles.
<TextInput className="your-class" id="testId1" />
You should use #material-ui/styles to extend your component's styles. Take a like at this answer, it's similar to your case: https://stackoverflow.com/a/67512965/8950820. Here is and example:
You should use #material-ui/styles to extend your Text Fields styles like this:
import React from 'react';
import { makeStyles, TextField } from '#material-ui/core';
const useStyles = makeStyles({
textField: {
border: 0,
borderRadius: 3,
padding: '0px 30px',
// Other styles here...
},
});
export default function MyComponent() {
const classes = useStyles();
return (
<div>
<TextField
size="large"
variant="outlined"
label="A text field title"
className={classes.textField}
/>
</div>
);
}
Learn more about the documentation at this link: #material-ui.com/styles

:focus issues with React

I'm relatively new with ReactJS and I'm trying to implement a small form that contains an input text field and a search button. I'm using the :focus pseudo-selector on the input field so when the user enters information it increases the width to 2000% and when the element loses focus it goes back to width:130%.
The problem I'm having is when I click my search button for the first time the input field shrinks back to the original position but it doesn't do the search until I click it for the second time. If I type something and then click somewhere else to loose focus it works like a charm.
Here's my code:
import React from 'react'
import Header from '../base/header'
import axios from 'axios'
import SearchResults from './searchResults'
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import Radium from 'radium';
class Search extends React.Component {
constructor(props) {
super(props)
this.state = {
searchTerm: "",
searchResultsList: ""
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleCallback = this.handleCallback.bind(this);
}
handleCallback() {
console.log("calling handleSubmit");
}
handleSubmit() {
var that = this
event.preventDefault();
axios.post('http://localhost:3000/users/findusers', {
searchTerm: this.state.searchTerm
}).then(function (response) {
console.log("data sent");
that.setState({searchResultsList: response.data})
}).catch(function (error) {
console.log(error);
});
}
handleChange(e) {
this.setState({searchTerm: e.target.value}, () => {
console.log(this.state.searchTerm);
});
}
render() {
return (
<div>
<Header/>
<form onSubmit={this.handleSubmit}>
<div>
<ReactCSSTransitionGroup
transitionName="search-input"
transitionAppear={true}
transitionAppearTimeout={500}
transitionEnter={false}
transitionLeave={false}>
<input
type="text"
style={styles.inputStyle}
value={this.state.searchTerm}
onChange={this.handleChange}
placeholder="Find Friends..."
/>
{/*<img onClick={() => this.handleSubmit()} */}
<img src="/icons/svg/magnifying-glass.svg"
alt="Search" className="searchIcon"
onClick={() => this.handleCallback()}
/>
</ReactCSSTransitionGroup>
</div>
</form>
<div className="container-fluid">
<div className="row">
<div className="col-md-3">left</div>
{/* Main Area */}
<div className="col-md-6">
<SearchResults
searchResultsList={this.state.searchResultsList}
/>
</div>
<div className="col-md-3">right</div>
</div>
</div>
</div>
)
}
}
const styles = {
inputStyle: {
marginTop: 5,
marginLeft: 20,
width: 130,
WebkitTransition: 'width 0.4s easeInOut',
msTransition: 'width 0.4s easeInOut',
':focus': {
width: '2000%'
}
}
};
export default Radium(Search)
I originally had the code in a separate CSS file and decided to make it inline to see if there was any difference. I tried creating different functions to see if there was any difference but is still behaving the same.
I would really appreciate any help!
In regards to the width changing when clicking the magnifying glass. I believe it is because the :focus property is on the input and not the div containing the input and img.
I would recommend using the :focus-within property on the parent div. Here is an example of divs with both properties.
#div1:focus-within > input {
width: 300px;
}
#div2 > input:focus {
width: 300px;
}
<div id="div1">
<input type="text"/>
<button>Search</button>
</div>
<div id="div2">
<input type="text"/>
<button>Search</button>
</div>
This should solve the focusing issue.
Not sure why your magnifying glass image works so strangely. When reading the code it seems that clicking the image calls handleCallback() which is only logging not submitting.
Not sure if this helps but I would recommend using a button or input element for submission. The button would have type="submit" with the magnifying glass image as the child. The input would have type="submit" value="" and set the CSS background-image: to the magnifying glass.

Categories