Retrieve form input and use it within a string - reactjs

I am trying to take input values from a form and output the results within a string. I don't want to use a database to do so.
Is this possible? Do I have to run the variables through a function? If so how can I go about it?
I'm new to react so providing pseudo-code could possibly make this more difficult than it needs to be but I will do my best.
<div className="form">
<form
name="contact"
method="POST"
>
//variable name
<input name="name" placeholder="Your Name" type="text" />
//variable age
<input name="age" placeholder="Your Age" type="number" />
//submit
<button>Send</button>
</form>
</div>
Based on the form above I expect to be able to somehow fetch the input values in the form after submit and have them display within a string.
Ex: Your name is "name" and your age is "age".
The result would be displayed on the same page if possible.
Thank you in advance for any help provided.

I could write you a bunch of theories, facts, and opinion-based statements.
Instead of that, I've chosen to write down the code. Look at the comments for more insight into the workflow, and if you have any questions, I'll be here to provide help.
Run the code snippet and see ti in action.
class FormComponent extends React.Component {
constructor(props) {
super(props);
this.state = {name: '', age: null, submitted: false}; // Here we're saving our input values
}
// Let's handle the input changes
// This is a great approach, since we don't need to write multiple 'onChange' handlers.
// Depending on what's the current 'name' of the input, we're assigning the currently entered value.
// We're accessing it via the 'e' -event parameter that's automatically passed to us
handleChange = (e) => {
this.setState({[e.target.name]: e.target.value});
}
// This is our onSubmit handler
handleSubmit = (e) => { // same e parameter
const { name, age, submitted } = this.state; // here we're doing a bit od es6 destructuring
// Instead of showing that 'alert' we'll change the 'submitted' part of the state to true. This check is going to be useful when we come to the part where we want to check if the user has clicked the button if YES, this part will be equal to true and we'll show them the output if not, nothing will be shown.
// alert(`Your name is ${name} and you're ${age} years old`);
this.setState({ submitted: true });
e.preventDefault();
}
render() {
// Here we're doing that destructuring again.
// So, later on we can use e.g. 'name' inseatd of 'this.state.name'
const { name, age, submitted } = this.state;
return (
<div>
<form onSubmit={this.handleSubmit}>
<label>
Name:{' '}
<input
/* This the above used 'name' property -> e.target.name */
name='name'
type="text"
/* Setting the current value from the current
state value and making this into a controlled
form which is what we want 99% of the time */
value={this.state.name}
/* Here we are passing in a reference to our
'handleChange' functions to the built-in
'onChange' method */
onChange={this.handleChange}
required />
</label>
<br />
<br />
<label>
Age:{' '}
<input name="age"
type="number"
value={this.state.age}
onChange={this.handleChange}
required />
</label>
<br />
<br />
<input type="submit" value="Submit" />
</form>
<br />
{/* Here will be our output. What we're doing here is checking if the FORM was submitted.
//If that's true then we want to show our newly created string, but if not, we don't want to show anything in that case -> 'null' */}
{submitted ? <p>{`Your name is ${name} and you are ${age} years old.`}</p> : null}
</div>
);
}
}
ReactDOM.render(
<FormComponent />,
document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Related

React can not use conditionally rendering on a component due to variables being nested inside of my form

I want to conditionally render a component in this case if the user submits a wrong answer, the input is stored as a javascript object called data and gets converted to a string called userInput.
After looking around, I got recommended to create a conditional rendering with a state outside of the form, but the problem I ran across is that since the variables are initialized inside of my form, i can't use ternaries to conditionally render my component in so I'm a bit stuck in what to do.
<main class="gameSection">
<h1>Welcome to League of Wordle!</h1>
<form
onSubmit={handleSubmit((data) => {
let userInput = data.guess;
console.log(userInput);
const championList = Object.keys(champions);
if (userInput.valueOf().toUpperCase() !== correctChampion.valueOf().toUpperCase()) {
<Wrong text="Class" alt="wrong img" img={wrong} />
}
})
}
>
<input
{...register("guess")} class="guess_input" placeholder="Enter Champion Name Here" type="text" />
<input class="guess_input" type="submit" />
</form>
</main>
I suggest you create a state to track if any answers submitted is wrong.
const [isWrong, setIsWrong] = useState(false)
Now, after each submit, update isWrong's value based on input.
onSubmit={handleSubmit((data) => {
let userInput = data.guess;
console.log(userInput);
const championList = Object.keys(champions);
if (userInput.valueOf().toUpperCase() !== correctChampion.valueOf().toUpperCase()) {
setIsWrong(true)
}
else {setIsWrong(false) } // logic in case of correct answer
})
}
Finally, you can implement conditional rendering:
<main class="gameSection">
<h1>Welcome to League of Wordle!</h1>
<form
...
>
<input
{...register("guess")} class="guess_input" placeholder="Enter Champion Name Here" type="text" />
<input class="guess_input" type="submit" />
{isWrong && <Wrong text="Class" alt="wrong img" img={wrong} /> }
</form>
</main>

In this basic react application, why does the custom component `TextInput` allow me to type stuff in even though the regular `input` field doesn't?

I have a basic react form that I am testing out currently. It's still incomplete, but I have discovered unexpected behaviour.
The regular input field doesn't allow me to type in anything, as I am not updating the state yet. However, my custom TextInput component does allow me to type stuff in... Surprising, as I said before, I am not using setValues to update the state yet.
import React, { useState } from 'react';
const App = () => {
const [values, setValues] = useState({
firstName: '',
lastName: ''
});
return (
<div>
<form>
{/* [EXPECTED] this doesn't allow anything to be typed in at the front-end... which is expected...
... as I am not using `setValues` to update the state yet */}
<input
type="text"
id="first-name"
name="firstName"
value={values.firstName}
/>
{/* [NOT EXPECTED] this does allow stuff to be typed in at the front-end... which is strange...
... as I am not using `setValues` to update the state yet */}
<TextInput
id="last-name"
name="lastName"
value={values.lastName}
/>
<button type="submit">
Register
</button>
</form>
</div>
);
};
const TextInput = props => {
return (
<input
type="text"
id={props.id}
name={props.name}
/>
/* <span id={props.id + '-error'}>{props.title}</span> */
);
};
export default App;
Can anybody help me to explain why the difference?
Your first input is controlled - it has a value prop which is used to determine what the value of the element should be when rendered:
<input
type="text"
id="first-name"
name="firstName"
value={values.firstName}
/>
No matter what you type into it, since it's "controlled", the value that exists in it will always be what's currently in state as values.firstName.
In contrast, your second input is uncontrolled. It has no value prop:
<input
type="text"
id={props.id}
name={props.name}
/>
So, since you're not giving React any directives on what its value should be while being rendered, you can type whatever you want into it, and it won't be in conflict with React state.

Do forms in React have bad performance?

I'm learning how to use <form>'s in React and most examples I've seen use a combination of state and onChange to keep track of your form's inputs:
class Form extends React.Component {
handleChange(event) {
this.setState({
inputvalue: event.target.value
})
}
render() {
return (
<form onSubmit={this.handleSubmit.bind(this)}>
<label>Name</label>
<input type="text" value={this.state.inputvalue} onChange={this.handleChange.bind(this)}/>
<input type="submit" value="Submit"/>
</form>
);
}
}
However, say I have numerous <input>'s and even some <textarea>'s which might change quite often. In that case each one of them would call the onChange method each time they are updated and the component would re-render on every key press.
Seeing as how people can type pretty fast, could this be an area for concern?
In a small testing I discovered that React successfully performs a shallow compare in the state and changes in the DOM in just the components that need a re-render. In Chrome I enabled the highlights (Paint Flashing) of the areas that were repainted by React in the DOM.
See the Paint Flashing in action.
In my example note that onChange will run on every keystroke to update the React state, the displayed value will update as the user types (based on the React Docs https://reactjs.org/docs/forms.html#controlled-components).
Also you can see my code here: https://codepen.io/anon/pen/KxjJRp
class Application extends React.Component {
state = {
value1: "",
value2: "",
value3: "",
value4: ""
}
onChange = ({target: {value, name}}) => {
this.setState({
[name]: value
})
}
render() {
const { state: { value1, value2, value3, value4 } } = this
return (
<div>
<label>Value 1</label>
<input type="text" value={value1} name="value1" onChange={this.onChange}/>
<label>Value 2</label>
<input type="text" value={value2} name="value2" onChange={this.onChange}/>
<label>Value 3</label>
<input type="text" value={value3} name="value3" onChange={this.onChange}/>
<label>Value 4</label>
<input type="text" value={value4} name="value4" onChange={this.onChange}/>
</div>
)
}
}
I am not totally sure of the best way to handle this but I could see an implementation of setting an onblur method to handle updating state. onChange would be constantly updating but this might not be the worst thing as it likely will not re-render the page with every keystroke.

Reactjs-how change the value of the data using textbox which is fethched from server

<ul>{this.state.data1.map(person =><li>
<form onSubmit={this.handleSubmit}>
<input type="text" name="fname" value={person.FirstName} onChange={this.onChange} className="box1" placeholder="Enter your first name" required />
</form>
</li>)}
</ul>
Here i was trying to display the data in textbox which can be editable
the data is fetched from server which is working
By using the above code,i can able to display the data in the textbox which is fetched
But i cant edit that data.
so please help me how to edit the data which was i displayed
You should not call onChange directly, Instead, you can create your own method and pass it to onChange:
handleChange = (e) => {
let state = Object.assign({}, this.state); // You should create a brand new Object
state[e.target.name] = e.target.value;
this.setState(state);
}
And then pass it to your input:
<input onChange={this.handleChange}/>
For a deeper explanation, check this doc

Send an array to a Redux Form to generate options in a select drop down

Working on the setting security questions part of the authentication. The server responds with a list of the 20 or so questions in the form of an array. I can get the form and select box to render, but only one option at a time by specifying the index.
If I try to send the entire array I get an undefined error. Tried to do a for loop in the ` to iterate through each index, which generated an error.
I'm trying to figure out how to pass the entire array so it makes an option for each entry in the array.
This is what I have so far:
// ./set_security_questions.js
// This renders errors regarding the form inputs
renderField(field) {
const {
label,
placeholder,
type,
name,
questions,
meta: {
touched,
error
}
} = field;
return (
<div className='form-group'>
<label>{label}</label>
<select className='form-control' name={name}>
<option value={questions}>{questions}
</option>}
</select>
<input
className='form-control'
type={type}
placeholder={placeholder}
{...field.input}
/>
<div className='text-danger'>
{touched ? error : ""}
</div>
</div>
);
}
// The main body to be rendered
render() {
if (this.props.permitRender) {
const { handleSubmit } = this.props;
return (
<div>
<h3>Set Security Questions</h3>
<p>Please select two security questions that will be easy for you to remember.</p>
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
{this.renderAlert()}
<Field
questions={this.props.questions.data.security_question}
label='Question 1'
placeholder='Answer 1'
name='a1'
type='text'
component={this.renderField}
/>
<Field
label='Question 2'
placeholder='Answer 2'
name='a2'
type='text'
component={this.renderField}
/>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
</div>
);
} else if (!this.props.permitRender) {
return (
<div> { this.renderAlert() } </div>
);
}
}
In addition, my JSON that comes back from the server looks pretty strange, so I will need to iron that out, but still wondering how to pass an array into the Form. this.props.questions.data:
data:
id: 123
key: "key_request"
security_q1: null
security_q2: null
security_question: Array(29)
0: {security_question: "In what city or town did you meet your spouse / partner?"}
1: {security_question: "In what city or town did your mother and father meet?"}
2: {security_question: "In what town or city was your first full time job?"}
3: {security_question: "What is the first name of your spouse's father?"}
......
Here is an example I'm currently using to populate a set of checkboxes. There isn't any special logic going on in the checkbox component, I just am using custom html for styling purposes.
Here is my data, a simple array:
const env = {
FONT_FORMATS: ['OTF', 'TTF', 'WOFF', 'WOFF2']
}
Here is the code in the render() function for my component. I'm storing each item in the Redux form under the object key -> fileTypes.
<ul className='tags'>
{envConfig.FONT_FORMATS.map((tag: string) => (
<Field
key={tag}
value={tag}
name={`fileTypes.[${tag}]`}
id={tag.toLowerCase().replace(' ', '_')}
type='checkbox'
component={checkBox}
label={tag}
/>
))}
</ul>
I hope this helps you out!

Resources