Puzant Bakjejian
Puzant Bakjejian

Reputation: 67

ReactJs & Styled components, Can't type anything in the input field

I'm working on personal project using ReactJs & styled Components.

I started to move all old css code to use styled-components instead, however I applied it on the Inputs as well, but now it stopped working and I can't type anything in these inputs.

I tried to search and read Styled-components Docs again, but alas couldn't find anything that can solve the issue

any help would be appreciated

import React, { Component } from 'react';
import Info from '@material-ui/icons/Info'
import Constants from '../../constants/Constants'
import {bindActionCreators} from 'redux'
import * as actions from '../../redux/actions/actionCreators.js';
import {connect} from 'react-redux'
import {Redirect} from 'react-router-dom'
import styled from 'styled-components'

class Login extends Component {
  constructor(props) {
    super(props)
    this.handleUsernameInput = this.handleUsernameInput.bind(this)
    this.handlePasswordInput = this.handlePasswordInput.bind(this)
    this.state = {
      username: null,
      password: null,
      validationErrorExsist: false,
      validationErrorText: null,
      isAuthenticated: this.props.isAuth
    }
  }

  GetErrorText = () => {
    //  username field is empty
    if(this.state.username == null) this.setState({ validationErrorText: Constants.VALIDATION_TEXT.EMPTY_USERNAME_FEILD })
    //  password field is empty
    else if(this.state.password == null) this.setState({ validationErrorText: Constants.VALIDATION_TEXT.EMPTY_PASSOWRD_FEILD })
  }

  handleUsernameInput = (event) => {
    this.setState({username: event.target.value})
  }
  
  handlePasswordInput = (event) => {
    this.setState({password: event.target.value})
  }

  login = () => {
    if((this.state.username == null || this.state.password == null)) {
      this.setState({validationErrorExsist: true}, () => {
        return this.GetErrorText()
      })
    }
    else {
      return this.props.loginUser(this.state.username, this.state.password)
    }
  }

  render() { 

    /** Login Styles Go Here */
    const LoginContainer = styled.div`
      padding: 10px;
      margin: 40px auto;
      width: 80%;
    `

    const LoginText = styled.div`
      font-size: 1.5em;
      font-weight: 600;
      margin-bottom: 20px;
    `

    const NoticeText = styled.div`
      line-height: 20px;
      margin-bottom: 16px;
    `

    const LoginButtonContainer = styled.div`
      display: flex;
      justify-content: flex-star;
      margin-top: 18px;
    `

    const LoginButton = styled.div`
      border-color: #01b4e4;
      background-color: #01b4e4;
      color: #fff;
      padding: .675rem .95rem;
      border-radius: 5px;
      font-weight: bold;
      border-radius: 14px;
      &:hover {
        cursor: pointer;
      }
    `

    const CreateNewAccountLink = styled.a`
      color: #00c6ff;
    `

    const LabelName = styled.div`
      font-weight: bold;
      margin-top: 15px;
    `

    const InputForm = styled.div`
      display: flex;
      flex-direction: column;
    `

    const StyledInput = styled.input`
      margin-top: 10px;
      border-color: rgba(33,37,41,0.15);
      color: #292b2c;
      padding: 12px;
      border-radius: .25rem;
      line-height: 1.5;
      vertical-align: middle;
      &:focus {
        outline: none
      }
    `

    const ErrorCardContainer = styled.div`
      margin: 20px 0 10px 0;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
      background-color: #fff;
      border-radius: 8px;
      border: 1px solid #ccc;
    `

    const ErrorCardHeader = styled.div`
      background-color: #d53540;
      color: #fff;
      display: flex;
      padding: 20px;
      border-top-left-radius: 7px;
      border-top-right-radius: 7px;
    `

    const ErrorText = styled.div`
      font-weight: 600;
      font-size: 1.2em;
      line-height: 1.2em;
      margin-left: 5px;
    `

    const ErrorTypeContainer = styled.div`
      padding: 5px;
    `

    const StyledUnorderedList = styled.ul`
      line-height: 1.4;
    `

    if(this.state.isAuthenticated) return <Redirect to='/' />
        
    const {validationErrorExsist} = this.state

    const ErrorStatusCard = () => (
      <ErrorCardContainer>
        <ErrorCardHeader>
          <Info />
          <ErrorText>There was a problem!</ErrorText>
        </ErrorCardHeader>
        <ErrorTypeContainer>
          <StyledUnorderedList>
            <li>{this.state.validationErrorText}</li>
            {/* TODO: login attemps */}
            {/* <li>You have 10 remaining login attempts.</li> */}
          </StyledUnorderedList>
        </ErrorTypeContainer>
      </ErrorCardContainer>
    )

    return ( 
      <LoginContainer>

        <LoginText>Login to your account</LoginText>
        <NoticeText>
          This app gets its data from the TMDD APIs. To view your account information, login with your TMDb credentials in the form below. To create one, 
           <CreateNewAccountLink href="https://www.themoviedb.org/signup" target="_blank"> Click here</CreateNewAccountLink>
        </NoticeText>

        {validationErrorExsist && <ErrorStatusCard />}

        <InputForm>
          <LabelName>Username</LabelName>
          <StyledInput onChange={this.handleUsernameInput} type="text"/>
        </InputForm>

        <InputForm>
          <LabelName>Password</LabelName>
          <StyledInput onChange={this.handlePasswordInput} type="password"/>
        </InputForm>

        <LoginButtonContainer>
          {/* <div className="login-btn" onClick={this.login}>Login</div> */}
          <LoginButton onClick={this.login}>Login</LoginButton>
        </LoginButtonContainer>

      </LoginContainer> 
    );
  }
}

const mapStateToProps = (state) => { 
  return {
    isAuth: state.isAuth,
  }
}

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators(actions, dispatch)
}
 
export default connect(mapStateToProps, mapDispatchToProps)(Login);

Upvotes: 2

Views: 3023

Answers (2)

GalAbra
GalAbra

Reputation: 5138

What you're experiencing is actually the components being re-rendered whenever a change is introduced, resulting in empty inputs, regardless of what the change was before the re-render.

In order to resolve this, the styled components' definitions should reside outside the render function.
Please check this CodeSandbox for a full working demo of your code, with this simple change.

Upvotes: 2

Nemanja Lazarevic
Nemanja Lazarevic

Reputation: 1047

The issue is that your Styled inputs aren't receiving the additional attributes that you are passing. In this example onChange and text. Here is the reference of how to use use the passed props to attach the attributes to the input element.

https://styled-components.com/docs/api#attrs

You can also style your input inside your InputForm to avoid dealing with the mentioned issue above. This way you can just keep using the normal <input /> element.

const InputForm = styled.div`
  display: flex;
  flex-direction: column;
  input {
    margin-top: 10px;
    border-color: rgba(33,37,41,0.15);
    color: #292b2c;
    padding: 12px;
    border-radius: .25rem;
    line-height: 1.5;
    vertical-align: middle;
    &:focus {
      outline: none
    }
  }
`

Upvotes: 0

Related Questions