I am new to coding with React and having trouble displaying my form. I am especially having problems displaying the label and input in the browser, only the topbar and logo displays. There are also no errors in the console. I would really appreciate any advice on how to fix this problem.
Form.js:
import React, { Component } from 'react';
import classes from './Form.module.css';
class Form extends Component {
constructor(props) {
super(props);
this.state = {
username: ''
};
}
handleUsernameChange = (event) => {
this.setState({
username: event.target.value
});
};
render() {
return (
<div className={classes.Form}>
<label>Username</label>
<input
type="text"
value={this.state.username}
onChange={this.handleUsernameChange}
></input>
</div>
);
}
}
export default Form;
Form.module.js:
.input{
outline: none;
padding: 16px 22px;
border: 1px solid #dadce0;
font-size:18px;
border-radius:5px;
}
.input:focus{
border: 2px solid royalblue;
}
.label{
color: #8d8d8d;
position: absolute;
top: 27px;
left: 55px;
background: #ffffff;
transition: 300ms;
transform: translate(-50%, -50%)}
App.js
import React from 'react';
import './App.css';
import Topbar from './Topbar';
import Form from './Form';
function App() {
return (
<div className="App">
<Topbar />
<Form />
</div>
);
}
export default App;
Thanks in advance!
I changed the contents in Form.module.js to
.Form > input{
.Form > label{
and now both the label and input displays in the browser.
Related
I'm trying to transition a simple overlay if one of four thumbnails is clicked. My idea was to toggle the overlays opacity within the inline style of the element like this..
<div className='product-thumbnail-overlay' style={selectedThumbnail === id ? { opacity: 1 } : { opacity: 0 }}></div>
This is working until I wrap this code in a react function component to avoid repetitions of my code.
HTML
import { useState, useEffect } from 'react';
import './Product.scss';
import ProductImage1 from '../assets/images/image-product-1.jpg';
import ProductImage2 from '../assets/images/image-product-2.jpg';
import ProductImage3 from '../assets/images/image-product-3.jpg';
import ProductImage4 from '../assets/images/image-product-4.jpg';
import ProductThumbnail1 from '../assets/images/image-product-1-thumbnail.jpg';
import ProductThumbnail2 from '../assets/images/image-product-2-thumbnail.jpg';
import ProductThumbnail3 from '../assets/images/image-product-3-thumbnail.jpg';
import ProductThumbnail4 from '../assets/images/image-product-4-thumbnail.jpg';
const Product = () => {
const [selectedThumbnail, setSelectedThumbnail] = useState(1);
const getProductThumbnailById = (id) => {
// get the imported product thumbnail
};
const ProductThumbnail = ({ id }) => {
return (
<div className='product-thumbnail-container' onClick={() => setSelectedThumbnail(id)}>
<img src={getProductThumbnailById(id)} alt='thumbnail of product' className='product-thumbnail' />
<div
className='product-thumbnail-overlay'
style={selectedThumbnail === id ? { opacity: 1 } : { opacity: 0 }}
></div>
</div>
);
};
return (
<main>
<div className='product-images'>
<img src={ProductImage1} alt='product' className='product-image' />
<div className='product-thumbnails'>
<ProductThumbnail id={1} />
<ProductThumbnail id={2} />
<ProductThumbnail id={3} />
<ProductThumbnail id={4} />
</div>
</div>
<div className='product-details'></div>
</main>
);
};
export default Product;
important SCSS
.product-thumbnail-container {
position: relative;
flex: 20.5%;
cursor: pointer;
.product-thumbnail {
display: block;
max-width: 100%;
border-radius: variables.$br;
}
.product-thumbnail-overlay {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(255, 255, 255, 0.6);
border: 2px solid variables.$clr_prim_orange;
border-radius: variables.$br;
transition: all 2000ms ease-in-out;
}
}
Codepen with what im trying to accomplish (but with repetitions of code): https://codepen.io/Sandhexer/pen/JjLrZOQ?editors=0110
Codepen with current code: https://codepen.io/Sandhexer/pen/gOeGKpP?editors=0110
I think that the rerendering causes the element not to transition because the opacity doesnt really change. Is this right and does anyone know a solution or good workaround for this problem?
I'm making a React navbar with a hamburger menu icon, but I cannot figure out why my icon cannot be positioned absolutely to the right. Chrome dev tools indicates that both Top and Right properties (as well as any other margin/padding properties) are invalid property values on my hamburger icon (a div element), though my nav menu itself is able to be positioned absolutely to the right.
Navbar.jsx:
import React, { useState } from 'react';
import NavIcon from './NavIcon';
import NavMenu from './NavMenu';
import './navbar.css';
const Navbar = () => {
const [isOpen, setIsOpen] = useState('false');
return (
<nav>
<NavIcon isOpen={isOpen} setIsOpen={setIsOpen} />
<NavMenu isOpen={isOpen} setIsOpen={setIsOpen} />
</nav>
);
};
export default Navbar;
NavMenu.jsx:
import React from 'react';
import NavItem from './NavItem';
import './navbar.css';
const NavMenu = ({ isOpen }) => {
const slideIn = {
transform: () => isOpen ? 'translateX(1)' : 'translateX(0)'
};
return (
<ul className='Navbar__menu' isOpen={isOpen} style={slideIn}>
<NavItem title='Home' />
<NavItem title='About' />
<NavItem title='Contact' />
</ul>
);
};
export default NavMenu;
NavIcon.jsx:
import React from 'react';
import './navbar.css';
const NavIcon = ({ isOpen, setIsOpen }) => {
const toXTop = {
transform: isOpen ? 'rotate(-45deg) translate(-5.25px, 6px)' : 'none'
};
const toXMid = {
opacity: isOpen ? '0' : '1'
};
const toXbottom = {
transform: isOpen ? 'rotate(45deg) translate(-5.25px, -6px)' : 'none'
};
return (
<div className='Navbar__icon' isOpen={isOpen} onClick={() => setIsOpen(!isOpen)}>
<div className='Navbar__icon--bars' style={toXTop} />
<div className='Navbar__icon--bars' style={toXMid} />
<div className='Navbar__icon--bars' style={toXbottom} />
</div>
);
};
export default NavIcon;
NavItem.jsx:
import React from 'react';
import './navbar.css';
const NavItem = ({ title }) => {
return (
<div className='Navbar__menu--item'>
{ title }
</div>
);
};
export default NavItem;
navbar.css:
.Navbar__icon {
display: block;
position: absolute;
top: 5;
right: 5;
z-index: 1;
cursor: pointer;
}
.Navbar__icon--bars {
width: 25px;
height: 4px;
background-color: #666;
border-radius: 5px;
margin: 4px 0;
transition: 0.2s;
}
.Navbar__menu {
position: absolute;
width: 15em;
height: auto;
right: 0;
list-style: none;
background-color: #000;
}
.Navbar__menu--item {
font: 1rem Arial, sans-serif;
color: #999;
margin: 1em;
cursor: pointer;
}
App.js just renders the Navbar.jsx component.
Any advice is appreciated. Thanks.
It seems that Top/Left/Right/Bottom property values in React do not support unitless numerical values, as this issue was resolved by adding px units to my values.
Please forgive my confusion and newbiness. I'm trying to export a styled Button. Totally dazed and confused. Please help. I don't really want to export 2 buttons, as shown, but a single Button with the styles from the props, and the given styles as the default, I think :(
import React, {Component} from 'react'
import ReactDOM from 'react-dom'
import styled, { css } from 'styled-components'
export default class Button extends React.Component {
btn: Btn = (props) => {
styled.button`
border-radius: 3px;
padding: 0.25em 1em;
margin: 0 1em;
background: transparent;
color: palevioletred;
border: 2px solid palevioletred;
${props => props.primary && css`
background: palevioletred;
color: white;
`}
`
}
render(
<Btn>Normal Button</Btn>
<Btn primary>Primary Button</Btn>
)
}
And my App element in case it's relevant
import React, { Component } from 'react'
import 'containers/App.css'
import Button from 'components/Button'
export default class App extends Component {
render() {
return (
<div>
<p>
<Button primary="primary" label="Button Help" />
</p>
</div>
)
}
}
Define your Styled Button as follows
import React from 'react';
import styled, {css} from 'react-emotion';
const StyledButton = styled('button')`
border-radius: 3px;
padding: 0.25em 1em;
margin: 0 1em;
background: transparent;
color: palevioletred;
border: 2px solid palevioletred;
`;
const primary = css`
background: black;
color: white;
`;
export default class Button extends React.Component {
render() {
return (
<div>
<StyledButton className={this.props.primary && `${primary}`}>
{this.props.label}
</StyledButton>
</div>
);
}
}
and in app element use buttton as follows
import React, { Component } from 'react'
import 'containers/App.css'
import Button from 'components/Button'
export default class App extends Component {
render() {
return (
<div>
<p>
<Button label="Button Help" /> // for normal Styled Button
<Button primary label="Button Primary" /> // for Primary Styled Button
</p>
</div>
)
}
}
Is it possible to use pseudoclasses for styling components. I have checkbox which should display SVG image: checked/ unechecked for displaying state as selected/unselected. I can do this with passing props from parent. But i have been told it is possible by only css(styled components).
part of my code:
const CheckboxInput = styled.input`
&:checked, &:not(:checked) {
display: none;
}`;
const CheckboxLabel = styled.label`
cursor: pointer;
-webkit-user-select: none; /* Chrome/Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+ */
`;
function Checkbox(props) {
return (
<CheckboxLabel htmlFor="id" onChange={() => { props.onchange(); }}>
<CheckboxInput id="id" type="checkbox" checked={props.checked} value="cb" name="cb" />
<Span><SVG glyph={checked} width={17} height={17} /></Span>
<Span><SVG glyph={unchecked} width={17} height={17} /></Span>
{props.children}
</CheckboxLabel>
);
}
With following selector in styled-components you can use the state of the input/checkbox to modify the style with only CSS:
&:checked + ${Label} {
/* your CSS */
}
Here is a full example:
import React from 'react';
import { render } from 'react-dom';
import styled from 'styled-components';
const Label = styled.label`
background: red;
display: block;
padding: 1rem;
`;
const Input = styled.input`
&:checked + ${Label} {
background: blue;
}
`;
const App = () => (
<div>
<Input id="input" type="checkbox" />
<Label for="input" />
</div>
);
render(<App />, document.getElementById('root'));
You can see a preview of it here: https://codesandbox.io/s/oYQ21A4wz
This should give you a basic idea how to change style with CSS only.
I am looking at how I can update the border-box for an input element in my child component (UpdateInputBox) by passing a new class as a prop from the parent component (TextInput). If I inspect the input element, I can see the new class getting added to the input element but the styling doesn't update.
I have a feeling this is because my child component may not be rendering on props change.
Code below:
JSX File
import React from 'react';
import styles from './styles.scss';
export default class TextInput extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedStateForText: 'textInputNonFocussed'
}
this.changeInputState = this.changeInputState.bind(this);
}
changeInputState(e) {
this.setState({
selectedStateForText: e.target.value,
});
}
render() {
return (
<h1>Individual input Test Component</h1>
<UpdateInputBox updateClass={this.state.selectedStateForText}/>
<form className='textInputStyleSelector' onChange={this.changeInputState.bind(this)}>
<input type='radio' name='class' value='textInputNonFocussedValid' checked={this.state.selectedStateForText === 'textInputNonFocussedValid'} />Non-Focussed Valid
<input type='radio' name='class' value='textInputFocussedValid' checked={this.state.selectedStateForText === 'textInputFocussedValid'} />Focussed Valid
<input type='radio' name='class' value='textInputNonFocussedInvalid' checked={this.state.selectedStateForText === 'textInputNonFocussedInvalid'} />Non-Focussed Invalid
</form>
</div>
);
}
}
class UpdateInputBox extends React.Component {
constructor(props){
super(props);
this.state= {
updateClass: props.updateClass
}
}
render() {
return (
<input id='inputStyleComponents' className={this.state.updateClass} placeholder='Label text *' type='text' />
);
}
}
Style SCSS file
$titanium: #686868;
$font-input-placeholder: Regular;
$font-size-small: 12px;
$emerald: #3dc238;
$ruby: #a3403e;
.textInputContainer {
background-color: white;
}
.inputStyleComponents {
display: inline-block;
margin: 10px;
}
// placeholder default css
::-webkit-input-placeholder { /* Chrome/Opera/Safari */
color: $titanium;
font-family: $font-input-placeholder;
font-size: $font-size-small;
}
::-moz-placeholder {
color: $titanium;
font-family: $font-input-placeholder;
font-size: $font-size-small;
}
:-ms-input-placeholder {
color: $titanium;
font-family: $font-input-placeholder;
font-size: $font-size-small;
}
// Text Field Non Focussed class (styles can be applied to the input element but defining a class for testing)
input[type=text] {
border: 1px solid $titanium;
border-radius: 3px;
padding: 8px 10px;
vertical-align: middle;
outline: none;
}
input[type=text]:focus, .textInputFocussed {
box-shadow: 0px 0px 5px lavender;
}
.textInputNonFocussedValid {
box-shadow: 0px 0px 5px $emerald;
}
.textInputFocussedValid {
box-shadow: 0px 0px 5px springgreen;
}
.textInputNonFocussedInvalid {
box-shadow: 0px 0px 5px $ruby;
}
.textInputFocussedInvalid {
box-shadow: 0px 0px 5px crimson;
}
input[type=text]:disabled {
opacity: 0.5;
background-color: #fff;
}
input[type=radio] {
margin: 10px;
}
When your parent component state updates, your child state does not gets updated like you believe. The UpdateInputBox constructor will run only once and so your state for UpdateInputBox will be set only once. You have to update your UpdateInputBox state, based on the props you receive in the componentWillReceiveProps. You have to do something like below. Hope this helps.
class UpdateInputBox extends React.Component {
constructor(props){
super(props);
this.state= {
updateClass: props.updateClass
}
}
componentWillReceiveProps(nextProps) {
if(this.props.updateClass !== nextProps.updateClass) {
this.setState({updateClass: nextProps.updateClass});
}
}
render() {
return (
<input id='inputStyleComponents' className={this.state.updateClass} placeholder='Label text *' type='text' />
);
}
}
Check the classname in the scss file. I don't see any rule defined for the the class textInputNonFocussed. Try defining a rule for this class with the styles you wanted to apply.
Eg:
input.textInputNonFocussed {
color: gray;
}
This should solve the problem as you have mentioned that the class is added.
#Panther:
The React Lifecycle hook helped me with getting the updated values. I had to make some additional changes to the code though as I am importing the .scss file and storing it as styles
import styles from './styles.scss';
because of that I had to use my classNames as:
<input className={styles.textInputFocussedValid} placeholder='Label text *' type='text' />
As my new class value is stored in the state using:
<input className={this.state.updateClass} placeholder='Label text *' type='text' />
didn't work (as it is not linked to styles like styles.textInputFocussedValid).
I eventually used classnames by JedWatson to create the conditions as below:
const updatedClass = classnames(
{ [`${styles.textInputNonFocussedValid}`]: this.props.updateClass === 'textInputNonFocussedValid' },
{ [`${styles.textInputFocussedValid}`]: this.props.updateClass === 'textInputFocussedValid' },
{ [`${styles.textInputNonFocussedInvalid}`]: this.props.updateClass === 'textInputNonFocussedInvalid' },
{ [`${styles.textInputNonFocussedValid}`]: this.props.updateClass === 'textInputNonFocussedValid' },
{ [`${styles.textInputFocussedInvalid}`]: this.props.updateClass === 'textInputFocussedInvalid' },
);
return (
<input id='inputStyleComponents' className={updatedClass} placeholder='Label text *'type='text' />
);