Redux form props & typescript - javascript

Was looking for years, didn't find anything worthy tho.
When I was working with flow, I could simply:
import { type FieldProps, FormProps } from 'redux-form';
Is there a similar (and that easy) way to properly set props to redux form in typescript?
Docs aren't saying anything about typescript, there's only a page for Flow typings.
However, I found that I can import something like propTypes from redux-form:
import { reduxForm, propTypes } from 'redux-form'
However - redux-form has nothing like propTypes exported, so docs are kinda deprecated.
Link: https://redux-form.com/7.2.1/docs/api/props.md/
Thanks in advance for any kind of help.
tl;dr class RegistrationForm extends React.PureComponent<any> {
what to drop here ^^^^^

You need to install the #types/redux-form package with your package manager. The #types/redux-form package includes types definitions for redux-form package.
Then you can import type definitions from redux-form, for example InjectedFormProps.
Your form that will be wrapped with reduxForm() should has props that extends InjectedFormProps<FormData = {}, P = {}>.
reduxForm() type is generic reduxForm<FormData = {}, P = {}>(...
See the example:
import * as React from 'react';
import { reduxForm, InjectedFormProps, Field } from 'redux-form';
import { IUser } from './index';
interface IProps {
message: string;
}
class UserForm extends React.Component<InjectedFormProps<IUser, IProps> & IProps> {
render() {
const { pristine, submitting, reset, handleSubmit, message } = this.props;
return (
<form onSubmit={handleSubmit}>
<div>{message}</div>
<div>
<label>First Name </label>
<Field
name="firstName"
component="input"
type="text"
placeholder="First Name"
/>
</div>
<div>
<label>Last Name </label>
<Field
name="lastName"
component="input"
type="text"
placeholder="Last Name"
/>
</div>
<div>
<button type="submit" disabled={pristine || submitting}>
Submit
</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</div>
</form>
);
}
}
export default reduxForm<IUser, IProps>({
form: 'userForm',
})(UserForm);
The source code of #types/redux-form package is located here. You can see the types there and more complicated examples in the redux-form-tests.tsx file that is used for types checking.

Related

ReactJS and autofocus

I have a react-bootstrap modal with an <input>. I want to set the autofocus attribute on the <input>
The following works fine, but shows a warning in the console
<input type="text" autofocus='true' />
Warning: Invalid DOM property `autofocus`. Did you mean `autoFocus`?
The following options do not work, in the sense that they do not focus the input when opening the modal:
<input type="text" autoFocus='true' />
<input type="text" autoFocus={true} />
<input type="text" autoFocus />
What is the recommended way of setting autofocus. Or how should I mute the warnings for the example that works well?
Note: This is react 16.8.6
If you're using React Hooks, add useCallback() to your component and add a ref={callback} to the form control:
import React, { useCallback } from 'react'
function InputComponent() {
const autoFocus = useCallback(el => el ? el.focus() : null, [])
return <input type="text" ref={autoFocus} />
}
export default InputComponent
You can replace the <input> with a React Bootstrap FormControl too.
Refs is what you want,
constructor(props) {
super(props);
this.myRef = React.createRef();
}
componentDidMount(){
this.myRef.current.focus();
}
<input type="text" ref={this.myRef} />
If you are using react hooks, you could write your own simple auto focus hook:
import { useEffect, useState } from "react";
export const useAutoFocus = (inputId: string) => {
const [initialized, setInitialized] = useState(false);
useEffect(() => {
if(!initialized) {
document.getElementById("email").focus();
setInitialized(true);
}
});
};
and the simply use e.g.
useAutoFocus("email")
in your form.

Passing custom props to component with redux-form 7

I am using the following libraries
"#material-ui/core": "^3.0.3",
"react": "^16.5.0",
"redux": "^4.0.0",
"redux-form": "^7.4.2",
How do I pass custom props to my component property of the redux-form <Field />?
According to this example from redux-form everything I have below should work, but it is not pulling the multiline={true} or rows={2} props into the <TextField /> component.
I am not sure how it is supposed to work as I am a novice with javascript. Any help would be appreciated.
PostForm.js
import React from 'react'
import { Link, withRouter } from 'react-router-dom';
import { reduxForm, Field } from 'redux-form';
import Button from '#material-ui/core/Button';
import TextField from '#material-ui/core/TextField'
class PostForm extends React.Component {
renderTextField = ({ input,
label,
meta: { error, touched } },
...custom) => {
return (
<TextField
name={label}
label={label}
{...input}
{...custom}
/>
);
};
onSubmit(event) {
event.preventDefault();
const { submitPost, history, formValues } = this.props;
submitPost(formValues.values, history);
}
render() {
<form onSubmit={this.onSubmit.bind(this)}>
<Field
name="title"
component={this.renderTextField}
label="Title"
/>
<Field
name="body"
component={this.renderTextField}
label="Body"
multiline={true}
rows={2}
/>
<div className={classes.buttonContainer}>
<Button to="/posts" component={Link} className={classes.button} color='secondary'>
Cancel
</Button>
<Button type='submit' className={classes.button} color='primary'>
Next
</Button>
</div>
</form>
}
}
export default reduxForm({
validate,
form: 'postForm',
destroyOnUnmount: false
})(PostForm)
To render multi line fields, you need to pass multiLine={true} (notice the camel casing - this is important). This is based on docs linked from https://github.com/erikras/redux-form-material-ui which seem like old version. According to newer docs, it seems multiline is all lowercase (leaving it here for posterity's sake).
Update
Also, ...custom is outside of the curly braces. Should be
renderTextField = ({ input, label, meta: { error, touched } , ...custom })
A bit about how Field passes props down - it's not enough to cover everything in this answer but I can give a few pointers to help you get started.
<Field ... /> is JSX notation. While JSX makes it easy to read and wirte HTML constructs, [React actually doesn't need JSX][1]. Internally, they all compile to pure JS functions (using React.createElement and other factory functions).
After that, passing ...custom etc. is just rest/spread operators introduced in ES6. They are shortcuts, and you can use React without them as well (meaning you can use just ES5 syntax).

React Form with file submission

I am now practicing upload a file by using Reactjs. This is a simple problem, but I could not connect the solution to axios. I know how the state and Form works, but my JavaScript callback values does not contains any of my given input. Or I could not find my values. Here is my case.
import React, {Component, Fragment} from 'react';
import tokamakConfig from './Configuration_icon_by_obsilion.png';
import {Form} from 'semantic-ui-react';
class Advance extends Component {
handleSubmit(event, values){
console.log(event);
console.log(values);
}
render() {
return (
<Fragment>
<h1>Please provide necessary information for the operation</h1>
<img src={tokamakConfig} alt={'tokamak configuration'} />
<Form onSubmit={this.handleSubmit}>
<Form.Group inline>
<label>Load input file</label>
<input name={'file'} type='file' />
</Form.Group>
<Form.Group inline>
<label>Comment</label>
<input name={'comment'} type={'text'} placeholder={'This is an advanced mode'}/>
</Form.Group>
<button type={'submit'}>Submit</button>
</Form>
</Fragment>
)
}
}
export default Advance;
In my console.log(). I got proxy object and onSubmit object. I could not find any of my input there. Then I have no idea how can I dispatch my value to axios
Question:
How to POST file from form to endpoint
<input type="file" onChange={ (e) => this.handleChange(e.target.files) } />
You need to use onChange event to get the file data.
handleChange(selectorFiles: FileList)
{
console.log(selectorFiles);
}
Then you need to get the file info inside the method

Uncaught TypeError: this.props.xxx is not a function in React

I'm using React.js for a project and I'm getting some troubles. Here is my problem:
I have this component which is for creating a new recipe:
import React, {Component, PropTypes} from 'react';
import { reduxForm } from 'redux-form';
import {Link} from 'react-router';
import { createRecipe } from '../actions/index';
class NewRecipe extends Component {
static contextTypes = {
router:PropTypes.object
};
onSubmit(props){
this.props.createRecipe(props).then(() => {
this.context.router.push('/yourRecipes');
});
}
render(){
const name = this.props.fields.name;
const description = this.props.fields.description;
const handleSubmit = this.props.handleSubmit;
return(
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<h3>New recipe</h3>
<div>
<label>Name</label>
<input type="text" className="form-control" {...name} />
</div>
<div>
<label>Description</label>
<input type="text" className="form-control" {...description} />
</div>
<button type="submit" className="btn btn-primary btn-primary-spacing">Submit</button>
<Link to="/yourRecipes" className="btn btn-danger btn-primary-spacing">Cancel</Link>
</form>
);
}
}
export default reduxForm({
form: 'NewRecipeForm',
fields: ['name','description']
}, null, { createRecipe })(NewRecipe);
createRecipe action creator looks like this inside index.js file:
export function createRecipe(props){
const request = axios.post('http://localhost:3001/recipes/new', props);
return {
type: CREATE_RECIPE,
payload: request
};
}
Everytime I try to click the submit button of the form I get this error in the browser console:
Uncaught TypeError: this.props.createRecipe is not a function
The error is because there is not such function defined in this react class and you are trying to access it using this.props.createRecipe.
One way is you would directly call as createRecipe() as you have the import.
One more way is you use connect from react-redux and connect this class with the state and dispatch props and then you can use this.props.createRecipe()
If you are using redux-form 6.x.x then you need to make use of connect
NewRecipe = reduxForm({
form: 'NewRecipeForm',
fields: ['name','description']
}, null)(NewRecipe);
export default(null, createRecipe)(NewRecipe);

How I can get post values in edit with React/Redux form in React

I am making simple blog with react redux. As package I am using redux form
I made events such as post,get,delete but I couldn't form edit because I can't getting values title and body in edit. I tried to solve it with initialize in componentwillMount but it is getting error to Cannot read property 'title' of undefined when I write this.props.edit.title in ComponentWillMount
How can I solve this problem, How I can get values in edit form
import React, { Component, PropTypes } from 'react';
import * as actions from '../../actions/index';
import { connect } from 'react-redux';
import {reduxForm} from 'redux-form';
import {initialize} from 'redux-form';
class EditPost extends Component {
componentWillMount(){
this.props.dispatch(initialize('edit', { title: this.props.edit.title }, ['title', 'body']));
this.props.EditPost(this.props.params.id);
}
handleFormSubmit(formProps){
this.props.addPost(formProps);
this.context.router.push('/posts');
}
render(){
const {handleSubmit,fields:{title,body}} = this.props;
if(!this.props.edit){
return <div>Loading...</div>;
}
return (
<div>
<div className="row">
<div className="col-md-12">
<form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
<fieldset className="form-group">
<label>Title:</label>
<input {...title} className="form-control" />
{title.touched && title.error && <div className="text-danger">{title.error}</div>}
</fieldset>
<fieldset className="form-group">
<label>Body:</label>
<textarea {...body} className="form-control" ></textarea>
{body.touched && body.error && <div className="text-danger">{body.error}</div>}
</fieldset>
<button className="btn btn-success">Add</button>
</form>
</div>
</div>
</div>
);
}
}
function mapStateToProps(state) {
return {
edit:state.posts.edit
}
}
export default reduxForm({
form:'edit',
fields:['title','body'],},mapStateToProps,actions)(EditPost);
I solved problem in following way. I can get the post values with initialValues: state.posts.edit
function mapStateToProps(state) {
return {
edit:state.posts.edit,
initialValues: state.posts.edit
}
}

Categories

Resources