So I've been learning react but I'm having some trouble with forms.
I'm able to change a state after clicking a button in a form. However I've only been able to find resources that show me how to alert the new state.
What if I want to render the new state into the DOM?
I don't necessarily need the answer but would love to be shown the resources to figure out the answer myself to help me learn.
Here's what I've got:
import React from 'react';
import ReactDOM from 'react-dom';
class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = { username: '',};
}
myChangeHandler = (e) => {
this.setState ({username: e.target.value});
}
mySubmitHandler = () => {
alert(this.state.username);
}
render() {
return (
<form>
<p>Enter your name, and submit:</p>
<input
type='text'
onChange={this.myChangeHandler}
/>
<button onClick={this.mySubmitHandler}>Submit</button>
</form>
);
}
}
ReactDOM.render(<MyForm />, document.getElementById('root'));
Make a state for display as the part of component state.
class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = { userNameForInput: '', userNameForDisplay: ''}; // add 'userNameForDisplay'
}
myChangeHandler = (e) => {
this.setState ({ userNameForInput: e.target.value });
}
mySubmitHandler = () => {
this.setState ({ userNameForDisplay: this.state.userNameForInput }); // update `userNameForDisplay` by 'userNameForInput'
}
render() {
const { userNameForInput, userNameForDisplay } = this.state
return (
<form>
<p>Enter your name, and submit:</p>
<input
type='text'
onChange={this.myChangeHandler}
/>
<button onClick={this.mySubmitHandler}>Submit</button>
{/* render 'userNameForInput', 'userNameForDisplay' to DOM */}
{/* the format to render js variable in jsx is '{ jsVariable }' */}
<div>UserName From Input(update by input change): { userNameForInput }<div>
<div>UserName For Submit(update by submit button): { userNameForDisplay }<div>
</form>
);
}
}
Related
I'm currently working on a project that uses QuillJS for a rich text editor. I need to post the rich text content to my backend but I'm not sure how to access the QuillJS output.
In RichTextEditor.js
import React, { Component } from "react";
import ReactQuill from "react-quill";
import "react-quill/dist/quill.snow.css";
class RichTextEditor extends Component {
constructor(props) {
super(props);
// this.formats = formats;
this.state = { text: "" }; // You can also pass a Quill Delta here
this.handleChange = this.handleChange.bind(this);
}
handleChange(value) {
this.setState({ text: value });
const text = this.state;
console.log(text);
}
render() {
return (
<ReactQuill
value={this.state.text}
onChange={this.handleChange}
formats={this.formats}
modules={this.modules}
/>
);
}
}
export default RichTextEditor;
The console.log(text) basically just outputs the content of the rich text editor. Something like this "<p><em>aasdasdasd</em><strong><em>asdasdasdasd</em></strong></p>"
In Post.js
import React, { Component } from "react";
import RichTextEditor from "./RichTextEditor.js";
import "../../css/Post.css";
class Post extends Component {
constructor(props) {
super(props);
this.state = {
question: "",
};
}
onChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
console.log(this.state);
};
handleSubmit = (e) => {
e.preventDefault();
const { question } = this.state;
console.log("Question");
console.log(question);
render() {
const { question } = this.state;
return (
<div className="post">
<div className="post__container">
<form onSubmit={this.handleSubmit}>
<div className="post__richTextEditor">
<RichTextEditor value={question} onChange={this.onChange} name="question" />
</div>
</form>
</div>
</div>
);
}
}
export default Post;
I'm trying to update the state of the question but it doesn't seem to be updating. console.log(question) only outputs a single string.
How can I access the same string output from RichTextEditor.js?
Your RichTextEditor component should not handle change, it should only receive props from higher component:
class RichTextEditor extends Component {
constructor(props) {
super(props);
}
render() {
return (
<ReactQuill
value={this.props.value}
onChange={this.props.onChange}
formats={this.formats}
modules={this.modules}
/>
);
}
}
export default RichTextEditor;
Then your Post component pass value and onChange props to RichTextEditor:
class Post extends Component {
constructor(props) {
super(props);
this.state = {
question: "",
};
this.onChange = this.onChange.bind(this);
}
onChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
console.log(this.state);
};
handleSubmit = (e) => {
e.preventDefault();
const { question } = this.state;
console.log("Question");
console.log(question);
render() {
const { question } = this.state;
return (
<div className="post">
<div className="post__container">
<form onSubmit={this.handleSubmit}>
<div className="post__richTextEditor">
<RichTextEditor value={question} onChange={this.onChange} name="question" />
</div>
</form>
</div>
</div>
);
}
}
in RichTextEditor.js
handleChange(value) {
this.setState({ text: value });
const text = this.state;
console.log(text);
props.onChange(text); // passing the inner State to parent as argument to onChange handler
}
Now in Post.js
onChange = (newStateString) => {
//this.setState({ [e.target.name]: e.target.value });
console.log(newStateString); // you should get the string here
};
I'm trying to do a react app where you have a "login" screen (just add a username to go in).
I have used this tutorial to do what I want(basically after submitting a username, it should change the component rendering)
My problem is that each time I click the submit button and the main component re-renders it will change the state of the main component back to default. The result is that it will show the Game component, which is a generic one, for a split second then go back to rendering the login component. What am I doing wrong?
Main component:
class Main extends React.Component {
constructor(props){
super(props);
this.login = this.login.bind(this);
this.state = {
loggedIn : false
};
}
login() {
this.setState({loggedIn: true});
}
render() {
const isLoggedIn = this.state.loggedIn;
return (
<div>
{isLoggedIn
? <Game/>
: <Login login={this.login}/>}
</div>
);
}
}
The login component:
class Login extends React.Component {
constructor(props) {
console.log("HELLO")
super(props);
this.state = {
value: '',
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
event.preventDefault();
}
handleSubmit(event) {
// login/" + this.state.value
fetch("my.api.example")
.then(res => res.json())
.then(
(result) => {
this.onLogin();
},
(error) => {
console.log(error)
}
)
}
onLogin = () => {
this.props.login();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
Your handleSubmit doesn't have an event.preventDefault() so the form is submitting and refreshing the page.
Here is my simple to-do app program where I have made only one component which takes in the input form user and passes that input value to App.js to update items in App.js state.
todo-form.component.js
import React from 'react';
class SignInForm extends React.Component {
constructor(){
super();
this.state ={
temp: null
};
}
handleChange = (e) => {
e.preventDefault();
this.setState({
temp: e.target.value
},
console.log(this.state)
);
// this.props.addInput(e.target.value);
}
handleSubmit= (e) => {
e.preventDefault();
console.log(this.state.temp);
this.props.addInput(this.state.temp);
}
render(){
return(
<div className="container-form">
<form onSubmit={this.handleSubmit}>
<input
name="description"
type="text"
placeholder="add description"
onChange={this.handleChange}
value={this.state.input}
/>
<button type="submit">ADD</button>
</form>
</div>
);
}
}
export default SignInForm;
App.js
import React from 'react';
import './App.css';
import SignInForm from './components/todo-form/todo-form.component'
import ItemList from './components/todo-list/todo-list.component';
class App extends React.Component {
constructor(){
super();
this.state = {
input: []
};
}
addInput = (item) => {
let newInput=[...this.state.input,item];
console.log(newInput);
this.setState = ({
input: newInput
},
console.log(this.state)
);
}
render(){
return (
<div className="App">
<h1>TO-DO LIST</h1>
<SignInForm addInput={this.addInput} />
</div>
);
}
}
export default App;
On taking input the state inside todo-form.component.js is getting updated with the typed input value but on passing state.temp in handleChange function, the state inside App.js is not updating when addInput function is called.
Please help me on this issue and how my state is not getting updated in App.js??
Your setState is the problem. Have a look at my code.
App.js
class App extends React.Component {
state = {
input: [],
};
addInput = (item) => {
let newInput = [...this.state.input, item];
//setState should be this way
this.setState({
input: newInput,
});
};
render() {
return (
<div className="App">
<h1>TO-DO LIST</h1>
{this.state.input.map((el) => (
<li> {el}</li>
))}
<SignInForm addInput={this.addInput} />
</div>
);
}
}
export default App;
Login file.
class SignInForm extends React.Component {
// constructor(props) {
// super(props);
state = {
temp: null,
};
// }
handleChange = (e) => {
e.preventDefault();
this.setState({
temp: e.target.value,
});
// this.props.addInput(e.target.value);
};
handleSubmit = (e) => {
e.preventDefault();
console.log(this.state.temp);
this.props.addInput(this.state.temp);
};
render() {
return (
<div className="container-form">
<form onSubmit={this.handleSubmit}>
<input
name="description"
type="text"
placeholder="add description"
onChange={this.handleChange}
value={this.state.input}
/>
<button type="submit">ADD</button>
</form>
</div>
);
}
}
export default SignInForm;
I have a React component with an input field.
I want to update the value of the input field when a button is clicked, I can confirm that the value changes when I inspect element but it doesn't display in the input field. Below is a sample code to just to give an idea.
class InputField {
constructor(props) {
super(props)
}
state = {
userInput: ''
}
}
onClick = () => {
this.setState({
userInput: 'Test'
})
}
render() {
return ( <input value={this.state.userInput} name="sampleInput" />
<button onClick={this.onClick}> Click me </button>
)
}
Fix syntax
your code is ok, just little order.
I add the whole component
import React, { Component } from 'react';
class InputField extends Component {
constructor(props) {
super(props)
}
state = {
userInput: ''
}
onClick = () => {
this.setState({
userInput: 'Test'
})
}
render() {
return (
<div>
<input value={this.state.userInput} name="sampleInput" />
<button onClick={this.onClick}>Click me</button>
</div>
)
}
}
export default InputField;
I just removed syntax error in your example and it worked for me.
import React from 'react';
export default class InputField extends React.Component {
constructor(props) {
super(props)
this.state = {
userInput: ''
}
}
onClick = () => {
this.setState({
userInput: 'Test'
})
}
render() {
return (
<div>
<input value={this.state.userInput} name="sampleInput"/>
<button
onClick = {this.onClick}
>
Click me
</button>
</div>
)
}
}
One approach would be to implement this as a functional component via hooks. You could for instance use the state hook to store and render the userInput data as shown below:
import React from "react";
/* Declare functional InputField component */
function InputField () {
/* Define local state hook to store the "user input" data */
const [userInput, setUserInput] = React.useState("");
const onClick = (e) => {
/* Prevent button click's default behavior */
e.preventDefault();
/* Call the state's "setter" method to update "userInput" state */
setUserInput('Test')
}
/* Render both input and button in a <> fragment */
return (<>
<input value={this.state.userInput} name="sampleInput"/>
<button onClick={onClick}>Click me</button>
</>)
}
To use this component, simply render it as:
<InputField />
I just fix your syntax errors and it run no any error
class InputField extends React.Component {
constructor(props) {
super(props);
this.state = {
userInput: '',
};
}
onClick = () => {
this.setState({
userInput: 'Test',
});
};
render() {
return (
<div>
<input value={this.state.userInput} name="sampleInput" />
<button onClick={this.onClick}>Click me</button>
</div>
);
}
}
I am new to react and having hard time figuring on how to show up the value from another component to the edit file component. Basically, I am able to create a message using draft.js rich text editor and able to save it to the database in the backend. Now I need to work on the update/edit part. How do I get the description state value to show up in the rich text editor? Can anyone please help?
Create File
import { EditorState } from 'draft-js';
class CreateModal extends Component {
constructor(props) {
super(props);
this.state = {
description: EditorState.createEmpty()
};
this.handleEditorState = this.handleEditorState.bind(this);
}
handleEditorState(editorState) {
this.setState({
description: editorState
})
}
render() {
const { release } = this.props.state;
return (
<div>
...
<CreateForm
description={this.state.description}
handleEditorState={this.handleEditorState}
handleSubmit={(e) => handleSubmit(e)}
/>
...
);
}
}
Form file
import { Editor } from 'react-draft-wysiwyg';
import '../../react-draft-wysiwyg.css';
class CreateForm extends Component {
render() {
const { description, handleEditorState, handleSubmit } = this.props;
return (
<div>
<form className="form-horizontal" onSubmit={handleSubmit}>
<Editor
editorState={description}
onEditorStateChange={handleEditorState}
/>
{/* Buttons */}
<div className={`modal-footer ${styles.modalFooter}`}>
...
</div>
</form>
</div>
);
}
}
Edit file
class EditAccessInstructionModal extends Component {
constructor(props) {
super(props);
this.state = {
description: EditorState.createEmpty()
}
}
componentWillMount(){
this.setState({
description: this.props.accessInstructions.description
});
}
componentWillReceiveProps(nextProps) {
this.setState({
description: nextProps.accessInstructions.description
});
}
onDescriptionChange(event) { this.setState({ description: event.target.value }); }
render() {
const { description } = this.state;
return (
<div className="btn-group">
<div className={`modal-body ${styles['proj-modal-body']}`}>
<form id="modalForm" className="form-horizontal">
<Editor
value={description}
/>
</form>
</div>
</div>
)
}
}