React: On button click: Go to URL declared in input form - reactjs

I am trying to go to the URL, which is declared in the input field, when I click on the button. I am totally new to React, so any help would be appreciated!
This is the current Component:
class MyComponent extends React.Component {
render(){
return (
<form>
<input type="text" name="code" placeholder="http://www.google.de" />
<input type="button" value="Go" />
</form>
)
}
}

Making you input fully controlled should do the trick. Explanation in code comments
class MyComponent extends React.Component {
state = {
code: '' // initial value
}
// save code in state on change
setCode = e => this.setState({code: e.target.value})
// change href to be this.state.code value
go = e => {
e.preventDefault()
window.location.href = this.state.code
}
render(){
return (
<form>
{/* make input fully controlled */}
<input type="text" name="code" value={this.state.code} onChange={this.setCode} placeholder="http://www.google.de" />
{/* handle button click event*/}
<input type="button" value={`Go to ${this.state.code}`} onClick={this.go}/>
</form>
)
}
}
ReactDOM.render(<MyComponent/>, document.querySelector('#root'))
<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>
<div id="root" />

Following is solution by using refs:-
class App extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
submitHandler = () => {
let value = this.inputRef.current.value;
console.log(value);
if (value !== "") window.location.href = value;
};
render() {
return (
<form onSubmit={() => this.submitHandler()}>
<input
ref={this.inputRef}
type="text"
name="code"
placeholder="http://www.google.de"
/>
<input type="submit" value="Go" />
</form>
);
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
<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>
<div id='root' />

Related

Why data is not rendered on refresh in react js with asynchronous call?

I am creating edit form.First i have to get data to edit form and i am calling it in componentDidMount().Please see code below.
import React from 'react';
import CompanyForm from './CompanyForm';
import { connect } from 'react-redux';
import { companyActions } from '../../../redux/actions/company-action';
class EditCompanyPage extends React.Component {
constructor(props){
super(props);
};
componentDidMount () {
const { id } = this.props.match.params
const { dispatch } = this.props;
dispatch(companyActions.getCompany(id));
}
render(){
const {editUser } = this.props;
return(
<div>
<h1>Edit Company</h1>
{
editUser && <CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />
}
</div>
);
};
}
function mapStateToProps(state) {
const { editUser } = state.companyReducer;
return {
editUser
};
}
const EditCompany = connect(mapStateToProps)(EditCompanyPage);
export default EditCompany;
see code for CompanyForm component below:
import React from 'react';
class CompanyForm extends React.Component {
constructor(props){
super(props);
this.state = {
company :{
name : this.props.companyDataFP.name || '',
address1 : this.props.companyDataFP.address1 || '',
}
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
};
handleChange(e) {
const { name, value } = e.target;
const newState = Object.assign({}, this.state);
newState.company[name] = value;
this.setState(newState);
}
handleSubmit(e) {
e.preventDefault();
return false;
}
render(){
return(
<div className="col-md-12">
<form onSubmit={this.handleSubmit}>
<div className="row">
<div className="col-md-6">
<div className='form-group'>
<label htmlFor="name">Name</label>
<input type="text" name="name" className="form-control" onChange={this.handleChange} value={this.state.company.name} />
</div>
</div>
<div className="col-md-6">
<div className='form-group'>
<label htmlFor="address1">Address 1</label>
<input type="text" name="address1" className="form-control" onChange={this.handleChange} value={this.state.company.address1} />
</div>
</div>
</div>
<div className="row">
<div className="col-md-12">
<div className='form-group'>
<input type="submit" className="btn btn-info" value="submit" />
</div>
</div>
</div>
</form>
</div>
);
};
}
export default CompanyForm;
It works fine when i access this form with
<Link to="/edit-form/:id" >Edit</Link>
but when i refresh the current page then values are not rendering into form to edit.
I am using redux approach for state management, please guide me i am new to react.
Probably ComponyForm initializes form on its componentDidMount lifecycle function, so when editUser arrives nothing will change.
A way to handle this is changing:
<CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />
to:
{editUser.name && <CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />}

Editing input fields in react seeding with default

I have a bootstrap modal where a user is supposed to edit what he entered in a table. When I set-state using static getDerivedStateFromProps, the user cannot modify the input box, but when I manually initialize the state with some arbitrary data, the user can modify it. What am I doing wrong?
the component is getting its props from redux.
export default class EditItem extends Component {
constructor(props) {
super(props);
this.state = {
name: ""
};
}
handleChange = (event) => {
let { value, name } = event.target;
this.setState({
[name]: value
})
}
static getDerivedStateFromProps(nextProps, prevState){
return {
name: nextProps.itemDetails.name
}
}
render() {
let {
} = this.state;
let {itemDetails} = this.props
return (
<div id="myModal3" className="modal fade">
<div id={uuidv1()} className="modal-dialog">
<div id={uuidv1()} className="modal-content">
<div id={uuidv1()} className="modal-body">
<form id={uuidv1()} className="form-horizontal form-material">
{this.props.cat_name}
<div id={uuidv1()} className="form-group">
<label id={uuidv1()} className="col-md-8">
Item Name
</label>
<div id={uuidv1()} className="col-md-8">
<input
id={uuidv1()}
onChange={this.handleChange}
value={this.state.name}
name="name"
type="text"
placeholder="ex. Burrito"
className="form-control form-control-line"
/>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
}
Using getDrivesStateToProps is not a good option like that. You have a prop, why don't you use it directly? You can look here for more explanation.
Set your initial state to your prop:
class App extends React.Component {
constructor( props ) {
super( props );
this.state = {
name: this.props.itemDetails.name,
};
}
handleChange = ( event ) => {
const { value, name } = event.target;
this.setState( {
[ name ]: value,
} );
};
render() {
let { } = this.state;
const { itemDetails } = this.props;
console.log( this.state );
return (
<div>
<div>
<div>
<div>
<form>
{this.props.cat_name}
<div>
<label>Item Name</label>
<div>
<input
onChange={this.handleChange}
value={this.state.name}
name="name"
type="text"
placeholder="ex. Burrito"
className="form-control form-control-line"
/>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
}
const itemDetails = { name: "foo" };
ReactDOM.render(<App itemDetails={itemDetails}/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
If your prop is coming from an async operation, I don't know maybe you can use something like this just to be in the safe side:
this.state = {
name: ( this.props.itemDetails && this.props.itemDetails.name ) || "",
};
Maybe there is a better way ¯(°_o)/¯

How to get the text field value and push that value to an arrayList

How to get the text field value and push that value to an arrayList in react js?
I want to get the value from the text box and push it to Modules array so that i can render the values by iterating it.
I tried to use ref but getting error.
Can you help me?
constructor(props) {
super(props);
this.state={
module:'',
Modules: []
}
}
change (event){
this.setState({
[event.target.name]:event.target.value
});
};
createModule (e) {
e.preventDefault();
console.log("submitted",this.state.module);
this.setState(previousState => ({
...state,
thisModules: [...previousState.Modules, 'new value']
}));
};
render(){
return(
<form className="form-inline">
<div className="form-group">
Module Name:
<input type="text" id="module"
name="module"
placeholder="module"
className="form-control"
ref="Module"
value ={this.state.module}
onChange={event => this.change(event)}/>
<button type="submit" className="btn btn-primary" onClick={(event) => this.createModule(event)}>Add Module</button>
</div>
</form>
mylist.push(document.getElementById('textbox_id').value)
with mylist as your list and textbox_id as the id of the textbox should work.
Consider this is plain javascript as I don't really see any difference with react.
The main problem from running your code was that in createModule you weren't putting this in front of state. If you'd given details of the error this would have helped.
There were a few other typos, and a work solution is below.
class ModuleList extends React.Component {
constructor(props) {
super(props);
this.state={
module:'',
Modules: []
}
}
change (event){
this.setState({
[event.target.name]:event.target.value
});
}
createModule (e) {
e.preventDefault();
console.log("submitted",this.state.module);
this.setState(previousState => ({
...this.state,
Modules: [...previousState.Modules, this.state.module]
}));
};
render(){
return (
<form className="form-inline">
<div className="form-group">
Module Name:
<input type="text" id="module"
name="module"
placeholder="module"
className="form-control"
ref="Module"
value={this.state.module}
onChange={event => this.change(event)}/>
<button type="submit" className="btn btn-primary" onClick={(event) => this.createModule(event)}>Add Module</button>
</div>
<ul>
{
this.state.Modules.map(
(m) => <li>{m}</li>
)
}
</ul>
</form>
);
}
}
ReactDOM.render(
<ModuleList />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<p>My App:</p>
<div id='root' />

update list array from child component

new react user here.
i am trying to access form data in my parent app from the child form. I am trying to alert or console the data from the parent so I can visually see what was typed in the form. Once I can access the data in the parent I will try and move it to my list array.
PARENT
class App extends Component {
constructor() {
super();
this.state = {
lists: [],
items: {}
};
}
handleAddList(s) {
alert('I am calling function from child')
console.log(this.refs.id.value) // this errors out on me
}
render() {
return (
<div className="App">
<AddList addList={this.handleAddList.bind(this)} />
<div id="listsDiv" className="List">
<Lists lists={this.state.lists} items={this.state.items} addItem {this.handleAddItem.bind(this)} />
</div>
</div>
);
}
}
CHILD
class AddList extends Component {
handleSubmit(e) {
e.preventDefault();
alert(this.refs.id.value)
this.props.addList()
}
render() {
return (
<div id="addListDiv">
<form onSubmit={this.handleSubmit.bind(this)}>
<div id='addList'>
<label>What will be on your next list?
<input type='text' ref='id' id='newID'></input>
</label>
</div><br />
<input type='submit' value='Create List' />
</form>
</div>
);
}
}
You should set the ref on the input using a callback, like this:
<input type='text' ref={input => { this.input = input; }} id='newID'></input>
Then access it in your event handler like this:
alert(this.input.value);
However, if you are new to React, you should try using controlled components before you try to use refs.
https://reactjs.org/docs/forms.html
CHILD
import ReactDOM from 'react-dom';
class AddList extends Component {
handleSubmit(e) {
e.preventDefault();
var day = ReactDOM.findDOMNode(this.refs.id).value.trim();
this.props.addList(day);
}
render() {
return (
<div id="addListDiv">
<form onSubmit={this.handleSubmit.bind(this)}>
<div id='addList'>
<label>What will be on your next list?
<input type='text' ref='id' id='newID'></input>
</label>
</div><br />
<input type='submit' value='Create List' />
</form>
</div>
);
}
}
PARENT
class App extends Component {
handleAddList(args) {
console.log(args);
}
render() {
return (
<div className="App">
<AddList addList={this.handleAddList.bind(this)} />
</div>
);
}
}
Edit it a little to work for you.

Developing a generic React component to open and close arbitrary forms

I got the following snippet to open and close forms on my page:
<div>
{this.state.editFormOpen?
<div>
<Link
to=''
onClick={()=>{this.setState({editFormOpen:false})}}>
Close
</Link>
<PostForm
onSubmit={(post)=>this.createPost(post)}
/>
</div>:
<Link
to=''
onClick={()=>{this.setState({editFormOpen:true})}}>
Add post
</Link>}
</div>
Now in order to avoid repeating myself, I want to refactore that code into a seperate <FormHandler/> component, such that it works for arbitrary forms, not only
<PostForm/>. I.e., I need to be able to pass any form component to the <FormHandler/>.
How can I do this in React?
I will go about it by making a factory that returns a React Component, than render the children as props
const FormHandlerFactory = ({Form = PostForm}) => {
return class FormHandler extends React.Component {
render() {
return (
<div>
{this.state.editFormOpen?
<div>
<Link
to=''
onClick={()=>{this.setState({editFormOpen:false})}}>
Close
</Link>
<Form
onSubmit={(post)=>this.createPost(post)}
/>
</div>:
<Link
to=''
onClick={()=>{this.setState({editFormOpen:true})}}>
Add post
</Link>}
</div>
)
}
}
}
You can use this factory as
const FormHandler = FormHandlerFactory({Form: YourCustomFormComponent});
const App = (props) => (
<Form {...props}
)
You could create a stateless component that could render any children that you passed in that component you also need to put the states in the parent component
const ToggleForm = ({ editFormOpen, editFormHandler, children }) => (
<div>
{editFormOpen?
<div>
<Link
to=''
onClick={() => editFormHandler(false)}>
Close
</Link>
{children}
</div>:
<Link
to=''
onClick={() => editFormHandler(true)}>
Add post
</Link>}
</div>
);
class ParentCmp extends React.Component {
constructor(props) {
super(props);
this.state = {
editFormOpen: false,
}
this.editFormHandler = this.editFormHandler.bind(this);
this.createPost = this.createPost.bind(this);
}
editFormHandler(boolValue) {
this.setState({
editFormOpen: boolValue
});
}
render() {
return (
<div>
<ToggleForm
editFormOpen={this.state.editFormOpen}
editFormHandler={this.state.editFormHandler}
>
<PostForm
onSubmit={(post)=>this.createPost(post)}
/>
</ToggleForm>
</div>
)
}
}
You already have everything you need in order to accomplish that. Maybe just change the line where you render PostForm and accept props.children coming from your new component. With that you will be able to render any form you want inside of it.
Remember that the less business logic you keep outside of FormHandler the better. Each form should be aware of what to do on every field change or on submit.
For example, this.createPost should not be part of FormHandler in case you want to reuse it throughout your code.
class FormHandler extends React.Component {
constructor(props) {
super(props)
this.state = {
formOpen: false,
}
this.toggleFormOpen = this.toggleFormOpen.bind(this)
}
toggleFormOpen() {
this.setState({
formOpen: !this.state.formOpen,
})
}
render() {
return (
<div>
<button onClick={this.toggleFormOpen}>
{this.state.formOpen ? 'Close' : 'Open'}
</button>
{this.state.formOpen && React.cloneElement(
this.props.children,
{
onClose: this.toggleFormOpen
}
)}
</div>
)
}
}
const PostForm = ({ onClose, onSubmit }) =>
<form>
<input type="text" placeholder="Post Name" />
<input type="text" placeholder="Post Title" />
<input type="text" placeholder="Date" />
<button onClick={event => {
event.preventDefault()
onSubmit({ postName: '', postTitle: '', date: ''})
onClose()
}}>
Submit
</button>
</form>
const UserForm = ({ onClose, onSubmit }) =>
<form>
<input type="text" placeholder="First Name" />
<input type="text" placeholder="Last Name" />
<button onClick={event => {
event.preventDefault()
onSubmit({ firstName: '', lastName: '' })
onClose()
}}>
Submit
</button>
</form>
const App = () =>
<div>
<FormHandler>
<PostForm
onSubmit={formData => console.log('PostForm', formData)}
/>
</FormHandler>
<br />
<FormHandler>
<UserForm
onSubmit={formData => console.log('UserForm', formData)}
/>
</FormHandler>
</div>
ReactDOM.render(
<App />,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Resources