Reactjs: Form with multiple inputs does not submit - reactjs

JSBin: https://jsbin.com/qotuxofalo/edit?js,output
(^ uses ES6 class, so please use a latest browser to test)
If I comment out the second input the form submits, but does not submit with more than 1 input.
What am I missing?

You need to add a input of type submit to make the form work. Check the following examples. Adding that will submit the form on pressing enter. If you don't want that submit button, you can hide it using css.
Demo:
https://jsbin.com/mafafoxoji/1/edit?js,output

If desired, you can also access the text as it is being entered using the onChange event handler: https://jsbin.com/moqogag/edit?js,output
class App extends React.Component {
constructor(props) {
super(props)
this.handleChange = this.handleChange.bind(this)
}
handleChange(e) {
console.log("CHANGING")
console.log(e.target.value)
}
render() {
return React.DOM.form({ onChange: this.handleChange, action: "" }, [
React.DOM.input({ type: "text" }),
React.DOM.input({ type: "text" })
])
}
}
ReactDOM.render(
React.createElement(App),
document.getElementById("app")
)

Related

focus() doesn't set on input field after displaing (use refs)

Dumb React question: how to set focus on input after it displayed and why my code doesn't work? (Without display toggle it works.)
edit: What I expect: after click on a button, the input field appears (by removing .dnone class) and get a focus on it. (But it doesn't.)
My code:
import "./styles.css"; // with .dnone class with display:none
import React from 'react';
export default class App extends React.Component {
constructor(props) {
super(props);
this.input = React.createRef();
this.state = {
active: false
}
}
click = (e) => {
e.preventDefault();
this.setState({
active: true
});
this.input.current.focus();
}
render () {
return (
<div className="App">
<input type="text" ref={this.input} className={(this.state.active ? "" : "dnone")} />
<button type="button" onClick={(e) => this.click(e)}>click</button>
</div>
);
}
}
live demo: https://codesandbox.io/s/immutable-sea-9884z?file=/src/App.js:0-607
Thank you!
The issue is that React state updates are asynchronously processed, so in the click handler when you enqueue a state update you are immediately attempting to focus on the input, but since the active state hasn't updated yet you can't, the dnone classname hasn't been removed and input made visible yet.
Move the focus logic into the componentDidUpdate lifecycle method to "respond" to the active state updating.
componentDidUpdate(prevProps, prevState) {
if (prevState.active !== this.state.active && this.state.active) {
this.input.current.focus();
}
}
click = (e) => {
e.preventDefault();
this.setState({
active: true
});
}

writing a code for a basic form in react with a submit button in react

When I hit submit for the form, alert popup should be displayed, the submit button should be disabled till we close the the popup and then it should be enabled again .
Tried setting the initial state to false and then setting the state in submit function to true , but it is not working as the button gets disabled permanently unless I reload the page.
Not much is written as I don't know how to solve this issue.
I expect the submit button to be disabled till we close the alert popup and then get enabled but the submit button gets disabled permanently.
Try this
class App extends React.Component {
constructor(props) {
super(props);
this.click = this.click.bind(this);
this.state = {
buttonState: false
}
}
click(event) {
this.setState({
buttonState: true
});
setTimeout(() => this.setState(
{buttonState: false}),
1000
);
}
render() {
return (
<div className="button-state">
<button disabled={this.state.buttonState} onClick={this.click}>Click Me</button>
</div>
);
}
}
export default App;
Use Window confirm() Method and setstate on its response. for more detail click here

ReactJs redux form: initial values passed down to form not displaying

This is how my project looks:
class ParentOfForm extends Component{
constructor(){this.state={initVals: null};}
componentDidMount(){
asyncCall.then((values) =>
setState({
initVals: {
initval1: valFromAsync,
..
}
})
);
}
render(){
const {initVals} = this.state;
{!initVals && <Form/>}
{!!initVals && <Form initialValues={initVals}/>}
}
}
----------------
class Form extends Component{
constructor(props){
super(props);
this.state = {
initval1: "",
..
}
}
render(){
return(
<form..>
..
</form>
);
}
}
Form = reduxForm({
form: "Form",
validate,
enableReinitialize: true
})(Form);
export default Form;
So as you can see, I'm trying to use values from an async function as initialValues to initialize the input fields of my form. When I define initialValues inside Form = reduxForm({...}) they get displayed correctly. However when I try to set them dynamically using the async call I can see the values being changed but they all seem to be undefined eventhough I can see them being filled in with console.log(). What am doing wrong?
Obvious alternatives I can't use because reasons: defaultValue, const Form = ().., no parent
welcome to SO.
So what is happening is since its an async call the initValues don't show up immediately in the form.Even in the console log it'll show up once the call completes. So there is a time gap between the page loading with a blank form and then the init call completing with the values.
There are 2 ways to handle this :
Show a loading symbol on the form and wait for the async call to complete and fill the init values [UX recommended] see here
Show an empty form with default values till the initValues are fetched, and show them when the call completes. [bad UX practice]

Build dynamic URLs in React based on input

I have a list of items and I want to filter through them.
In order to do so I have a filtering component that looks like this:
[ text input "item name" ] [ dropdown "item category" ] [ date picker ]
I'm using React with Redux, react-redux and react-router. There's no "Filter" in my component, I want the items to get filtered as I type.
First of all I'm not sure how should I dynamically create the URL, so for example if you type "Abc" in the first input I want the current URL to be:
http://example.com/currentPage?filter=Abc&category=&dates=
As I type I want the URL to be changing constantly, so the URL actually builds as I type / choose options from dropdown / date picker. How could I achieve that with React Router?
Thanks
This is so straightforward. Just add onChange function to your input field. Like below.
import React from 'react';
class Filter extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
filter: '',
category: '',
dates: '',
}
}
handleChange(evt) {
this.setState({
filter: evt.target.value,
}, () => {
this.props.fetchFilteredItems(`http://example.com/currentPage?filter=${this.state.filter}&category=${this.state.category}&dates=${this.state.dates}`); // I assumed fetchFilteredItems comes from redux as an action.
});
}
render() {
return (
<div>
<input onChange={this.handleChange} />
<YourDropdown />
<YourDatePicker />
</div>
);
}
}
Hope this solves your problem.

React Call Youtube on Exit of Input

Im trying to use youtubes API with the you-tube-api search library, but am having some trouble getting new searches to happen.
I created a new function called search_youtube that I want to be called when a user exits the input. The way I have it setup now, the function is called continuously when I load the html page.
What is the appropriate way to solve this so that when a user exits the input a new search is rendered.
class SearchBar extends Component {
constructor(props) {
super(props)
this.state = {
videos: [],
selectedVideo: null
}
}
searchYoutube(event) {
console.log("called")
YTSearch({ key: API_KEY, term: event.target.value }, (videos) => {
this.setState({
videos: videos,
selectedVideo: videos[0]
})
});
}
render() {
return(
<div className="search-bar">
<input onBlur={this.search_youtube(event)} />
</div>
)
}
}
They are loading everytime you load your page because it's inside your render function, you are calling that function instead of passing the function to onBlur, change that line to this:
<input onBlur={event => this.search_youtube(event)} />
Obs. If you want to learn more about arrow functions check this article.

Resources