import React, { Component } from 'react';
import TaskBar from './Task';
class Todo extends Component {
state = {
todo: ''
}
changeHandler = (event) => {
console.log(event.target.value);
}
render() {
return (
<React.Fragment>
<div className="card">
<h5 className="card-header">Todo</h5>
<div className="card-body">
<h5 className="card-title">Task you want to do</h5>
<form>
<input type="text" className="form-control" value={this.state.todo} name="todo" onChange={(event) => this.changeHandler(event)} />
</form>
</div>
<button className="btn btn-primary">Go somewhere</button>
</div>
</React.Fragment>
)
}
}
export default Todo;
In the above code i don't know why i couldn't make any change
2) I am using Bootstrap cdn in my public folder and i am using these classes here
You forgot to set state inside your onchange handler.
import React, { Component } from 'react';
import TaskBar from './Task';
class Todo extends Component {
state = {
todo: ''
}
changeHandler = (event) => {
console.log(event.target.value);
this.setState({todo: event.target.value}) //you forgot to do this//
}
render() {
return (
<React.Fragment>
<div className="card">
<h5 className="card-header">Todo</h5>
<div className="card-body">
<h5 className="card-title">Task you want to do</h5>
<form>
<input type="text" className="form-control" value={this.state.todo} name="todo" onChange={(event) => this.changeHandler(event)} />
</form>
</div>
<button className="btn btn-primary">Go somewhere</button>
</div>
</React.Fragment>
)
}
}
export default Todo;
Link to a codesandbox example - https://codesandbox.io/s/jydjj?module=/example.js
Also currently your onchange uses an arrow function which creates a new function on every hit which is considered bad practice so i would suggest you to do this instead.
<input type="text" className="form-control" value={this.state.todo} name="todo" onChange={this.changeHandler} />
Related
I am learning react and I have a component which as a 2 input fields and a button, at the moment, clicking on the button will display a message in console log, but when the button is clicked it displays a popup Leave site?, Changes that you made may not be saved.
this is my code in this component
import React, { useRef, useState, Component } from 'react'
import { useAuthState } from 'react-firebase-hooks/auth';
import { useCollectionData } from 'react-firebase-hooks/firestore';
import { signOut } from 'firebase/auth';
class InfoLgnTest extends Component {
render() {
this.state = {
user: null
}
return (
<div>
<div className="App">
<SignInWithEmailPassword />
</div>
</div>
)
}
}
function SignInWithEmailPassword() {
const emailRef = useRef()
const passwordRef = useRef()
const signIn = () => {
console.log("InfoLgnTest singin clicked")
}
return (
<>
<div className="form">
<form>
<div className="input-container">
<label>Username </label>
<input
name="email"
type="text"
ref={emailRef}
required
placeholder ="something#gmail.com"
/>
</div>
<div className="input-container">
<label>Password </label>
<input
type="text"
name="pass"
ref={passwordRef}
required
placeholder ="..."
/>
</div>
<div className="button-container">
<input type="submit" onClick={signIn}/>
</div>
</form>
</div>
</>
)
}
export default InfoLgnTest
This code has a form, by default form send data as a request on the same page, for resolve this:
Add onSubmit to form,
call preventDefault method from event
call the function signIn
Change <input type="submit" ... /> to <button type="submit">Send</button>
function SignInWithEmailPassword() {
const emailRef = useRef()
const passwordRef = useRef()
const signIn = () => {
console.log("InfoLgnTest singin clicked")
}
// new function to handle submit
const submitForm = (event) => {
event.preventDefault();
signIn();
}
return (
<>
<div className="form">
{/* Add onSubmit */}
<form onSubmit={submitForm}>
<div className="input-container">
<label>Username </label>
<input
name="email"
type="text"
ref={emailRef}
required
placeholder ="something#gmail.com"
/>
</div>
<div className="input-container">
<label>Password </label>
<input
type="text"
name="pass"
ref={passwordRef}
required
placeholder ="..."
/>
</div>
<div className="button-container">
{/* Change input to button */}
<button type="submit">Send</button>
</div>
</form>
</div>
</>
)
}
I am trying to submit a file and text input to backend with POST request, the code looks like this,
state={
text:'',
file:''
}
handleTextChange = (e) => {
this.setState({[e.target.name]:e.target.value})
}
handleFileChange = (e) => {
this.setState({file:e.target.files[0]})
}
handleSubmit = (e) => {
const {text,file} = this.state
//POST request with text and file
}
But the file is always empty, If I console.log(e.target.files[0]), it shows a FileList in console but somehow it is not updated in state
I am quite new in react, your help is very much appreciated, thanks
EDIT: the form looks like this
<form action="" className="w-100" onSubmit={(e) => this.handleSubmit(e)}>
<div className="pt-1 pb-3">
<TextAreaAutosize
className="form-control"
placeholder="write some text here"
minRows="4"
name="text"
onChange={(e) => this.handleChange(e)}
/>
</div>
<div className="w-100 d-flex justify-content-between align-items-center">
<div>
<input
type="file"
className="form-control-file"
name="file"
onChange={(e) => this.handleFileChange(e)}
/>
</div>
<div>
<button type="submit" className="btn btn-primary">
Post
</button>
</div>
</div>
</form>
sandbox:
https://codesandbox.io/s/friendly-banzai-8ifw4?fontsize=14&hidenavigation=1&theme=dark
try this one works just fine
before install
run npm install #material-ui/core
import React, { Component } from 'react';
import './App.css';
import { TextareaAutosize } from '#material-ui/core';
class App extends Component {
constructor(props) {
super(props)
this.state = {
text: '',
file: ''
}
this.handleFileChange=this.handleFileChange.bind(this)
this.handleTextChange=this.handleTextChange.bind(this)
this.handleSubmit=this.handleSubmit.bind(this)
}
handleTextChange = (e) => {
this.setState({ [e.target.name]: e.target.value })
}
handleFileChange = (e) => {
console.log(e.target.files[0])
this.setState({ file: e.target.files[0] })
}
handleSubmit = (e) => {
const { text, file } = this.state
}
render() {
return (
<div className="App">
<form action="" className="w-100" onSubmit={(e) => this.handleSubmit(e)}>
<div className="pt-1 pb-3">
<TextareaAutosize
className="form-control"
placeholder="write some text here"
minRows="4"
name="text"
onChange={(e) => this.handleChange(e)}
/>
</div>
<div className="w-100 d-flex justify-content-between align-items-center">
<div>
<input
type="file"
className="form-control-file"
name="file"
onChange={(e) => this.handleFileChange(e)}
/>
</div>
<div>
<button type="submit" className="btn btn-primary">
Post
</button>
</div>
</div>
</form>
</div>
);
}
}
export default App;
I have a very simple component with a single state, I initialize the state when component is created and try to change it when a form is submitted.
It doesn't work for some reason.
import React, { Component } from "react";
export default class AddTodo extends Component {
constructor() {
super();
this.state = {
submited: false
};
}
handleSubmit = event => {
this.setState = {
submited: true
};
alert("Submited state: " + this.state.submited);
event.preventDefault();
};
render() {
return (
<div className="container mt-3">
<form onSubmit={this.handleSubmit}>
<div className="input-group mb-3">
<input
type="text"
className="form-control"
placeholder="New Todo Description Here"
/>
<div className="input-group-append">
<button className="btn btn-primary" type="submit">
Add Todo
</button>
</div>
</div>
</form>
</div>
);
}
}
this.setState is a function, so call it like one using brackets ().
this.setState({
submited: true
});
import React, { Component } from "react";
export default class AddTodo extends Component {
constructor() {
super();
this.state = {
submited: false
};
}
handleSubmit = event => {
this.setState({
submited: true
},()=>{
alert("Submited state: " + this.state.submited);
event.preventDefault();
});
};
render() {
return (
<div className="container mt-3">
<form onSubmit={this.handleSubmit}>
<div className="input-group mb-3">
<input
type="text"
className="form-control"
placeholder="New Todo Description Here"
/>
<div className="input-group-append">
<button className="btn btn-primary" type="submit">
Add Todo
</button>
</div>
</div>
</form>
</div>
);
}
}
As you can see here setState is a function, but you're assigning a value to it.
The problem is here:
this.setState = {
submited: true
};
It should be:
this.setState({submitted: true}); // Mind the typo also
Just to make a quick note, the React team published react hooks in version 16.8 as a replacement to class components that have some drawbacks. I would give it a try, the docs are here.
With hooks your code would look like this:
import React, { useState } from 'react';
function AddTodo() {
// Declare a new state variable, which we'll call "count"
const [isSubmitted, setSubmission] = useState(false);
function handleSubmit(event) {
setSubmission(true);
event.preventDefault();
}
return (
<div className="container mt-3">
<form onSubmit={handleSubmit}>
<div className="input-group mb-3">
<input
type="text"
className="form-control"
placeholder="New Todo Description Here"
/>
<div className="input-group-append">
<button className="btn btn-primary" type="submit">
Add Todo
</button>
</div>
</div>
</form>
);
}
Hi I need to pass two parameters, to the class Chat. Currently it is getting only one parameter and displaying correctly.
const Chat = props => (
<div >
<ul>{props.messages.map(message => <li key={message}>{message}</li>)}</ul>
</div>
);
This Chat.js file is called from the Home.js. Suppose I need to pass the Chat component two parameters and I tried it like following.
import React, { Component } from 'react';
import { User } from './User';
import Chat from './Chat';
export class Home extends Component {
displayName = Home.name
state = {
messages: [],
names: []
};
handleSubmit = (message,name) =>
this.setState(currentState => ({
messages: [...currentState.messages, message],
names: [...currentState.names,name]
}));
render() {
return (
<div>
<div>
<User onSubmit={this.handleSubmit} />
</div>
<div>
<Chat messages={this.state.messages,this.state.name} />
</div>
</div>
);
}
}
In this scenario how should I change the Chat component to accept two parameters and display inside div tags.
This is what I tried. But seems it is incorrect.
const Chat = props => (
<div >
<ul>{props.messages.map((message, name) => <li key={message}>{message}</li> <li key={name}>{name}</li>)}</ul>
</div>
);
PS: The User Method
import * as React from 'react';
export class User extends React.Component{
constructor(props) {
super(props);
this.state = {
name: '',
message: ''
}
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
render() {
return (
<div className="panel panel-default" id="frame1" onSubmit={this.handleSubmit}>
<form className="form-horizontal" action="/action_page.php" >
<div className="form-group">
<label className="control-label col-sm-2" htmlFor="name">Your Name </label>
<div className="col-sm-10">
<input type="text" className="form-control" name="name" placeholder="Enter your Name" onChange={this.handleChange} />
</div>
</div>
<div className="form-group">
<label className="control-label col-sm-2" htmlFor="message">Message</label>
<div className="col-sm-10">
<input type="text" className="form-control" name="message" placeholder="Enter your Message" onChange={this.handleChange}/>
</div>
</div>
<div className="form-group">
<div className="col-sm-offset-2 col-sm-10">
<button type="submit" id="submit" className="btn btn-default">Submit</button>
</div>
</div>
</form>
</div>
);
}
handleChange(evt) {
this.setState({ [evt.target.name]: evt.target.value });
}
handleSubmit = (e) => {
e.preventDefault();
this.props.onSubmit(this.state.message, this.state.name);
this.setState({ message: "" });
this.setState({name:""});
};
}
You can do this by using separate attributes to pass different props. So for instance, you might revise your <Home/> components render method like so:
<Chat messages={this.state.messages} names={this.state.names} />
and then to access these two bits of data (messages and name) from inside the <Chat /> component you could do the following:
const Chat = props => (
<div >
<ul>{props.messages.map((message, index) => <li key={message}>
From: { Array.isArray(props.names) ? props.names[index] : '-' }
Message: {message}</li>)}
</ul>
</div>
);
Hope this helps!
You have to pass them separately:
<Chat messages={this.state.messages} name={this.state.name} />
I am working on a React-Redux app, currently working on showing a modal box on a button click of a form. But I can't make it work. I have tried so many things but can't figure out why the modal box doesn't appear. Here is my code.
The Modal component file
import React from 'react'
import { connectModal } from 'redux-modal'
import { Button, Modal } from 'react-bootstrap'
import UpdatePasswordForm from 'forms/updatepassword'
export class UpdatePassword extends React.Component {
constructor(props) {
super(props)
}
renderCloseIcon (handleHide) {
return (
<button className='close' onClick={ handleHide }>
<span>
<i className="modal__close"/>
</span>
</button>
)
}
renderModalLogo () {
return (
<div className="modal__header modal__header_login">
<div className="modal__logo"></div>
</div>
)
}
render() {
const { show, handleHide } = this.props
return (
<Modal
show={ show }
onHide={ handleHide }
backdrop={ true }
className="modal_dark modal_center"
dialogClassName="modal-background-fix">
<div className="modal__container">
{ this.renderCloseIcon(handleHide) }
{ this.renderModalLogo() }
<div className="modal__content">
<UpdatePasswordForm onSubmit={() => {}}/>
</div>
</div>
</Modal>
)
}
}
export default connectModal({name: 'updatepassword'})(UpdatePassword)
The form that is loaded in the Modal
import React from 'react'
import { Field, reduxForm } from 'redux-form'
import Text from '../containers/Text'
const I18n = {}
I18n.t = Text.t
const UpdatePasswordForm = (props) => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<fieldset className="form-group">
<Field name="current_password" component="input"
type="password" placeholder="Password" className="form-control" />
</fieldset>
<fieldset className="form-group">
<Field name="password" component="input"
type="password" placeholder="New Password" className="form-control" />
</fieldset>
<fieldset className="form-group">
<Field name="password_confirm" component="input" type="password"
placeholder="New password confirmation" className="form-control" />
</fieldset>
<fieldset className="form-group form-group_btns">
<button type="submit" disabled={pristine || submitting} className="btn btn-primary btn-block">
{ 'CHANGE PASSWORD' }
</button>
</fieldset>
</form>
)
}
export default reduxForm({
form: 'updatepassword' // a unique identifier for this form
})(UpdatePasswordForm)
The file where modal is called
import React from 'react';
import './EditInformation.scss'
import { show } from 'redux-modal'
import UpdatePassword from './Modals/UpdatePassword'
// TODO fix stylee stylee
// TODO onChange is not updating correctly, FIX!
const EditInformation = ({ onSubmit, onChange, user, formSubmitting }) => {
return (
<div>
<UpdatePassword />
<form className='form-line form-line_light'>
<div className='col-xs-16 col-sm-8'>
<fieldset className='form-group'>
<button
onClick={(e) => {
show('updatepassword')
e.preventDefault()
}}
className='btn btn-secondary btn-lg profile-edit__addcard'
style={ { position: 'relative', top: '-27px' } }>
<i className='fa fa-plus'/>Vaihda salasana
</button>
</fieldset>
</div>
</form>
</div>
);
};
export default EditInformation;
In the beginning of our project, I tried to develope my own modal with all custom functionalities. Many problems has occured. I searched some open source projects, then I found a project on github. You should use react-modal, It's easy to use and well designed.
react-modal
There was a stupid mistake that I have figured out now. But I should get an error for that which I am not getting. I had to pass 'show' to the const EditInformation which I have done now and it is working all fine. Here is that part of the code:
const EditInformation = ({ onSubmit, onChange, user, formSubmitting, show }) => {
I wasn't passing 'show' previously.