Getting warning when i use withCookies() - reactjs

I am using react-cookie in my project. When i use withCookies() i am getting warning in console log like this
Warning: Failed prop type: Invalid prop component of type object
supplied to Route, expected function
How can i solve this.?
Below is the code
import React from 'react';
import { Form, Icon, Input, Button, Checkbox } from 'antd';
import { withCookies } from "react-cookie";
import './Login.css';
class NormalLoginForm extends React.Component {
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
console.log(values);
const { cookies } = this.props;
cookies.set('token', 'dfsfsd54dg2g45fg575f432sd4');
}
});
}
render() {
const { getFieldDecorator } = this.props.form;
return (
<div style={{ textAlign: 'center' }}>
<img className="logo-white" src={'https://cdn.medcampus.io/wp-content/uploads/2018/08/01131559/MC_Logo_Black.png'} alt="logo"/>
<div className="login-container">
<br/>
<Form onSubmit={this.handleSubmit} className="login-form">
<Form.Item>
{getFieldDecorator('email', {
rules: [{ required: true, message: 'Please input your Email id!' }, {
type: 'email', message: 'The input is not valid E-mail!',
}],
})(
<Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Email" size={"large"} />
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" size={"large"} placeholder="Password" />
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('remember', {
valuePropName: 'checked',
initialValue: true,
})(
<Checkbox>Remember me</Checkbox>
)}
<a className="login-form-forgot" href="">Forgot password</a>
<Button type="primary" size={"large"} htmlType="submit" className="login-form-button">Log in</Button>
</Form.Item>
</Form>
</div>
</div>
);
}
}
const Login = withCookies(Form.create({ name: 'normal_login' })(NormalLoginForm));
export { Login };

Following the comments, you are exporting all imports from your containers' files as default, so basically you'll get an object, not a function(the exact export).
To prevent this, there is several ways to do it:
Import your container in App from its own file.
in index.js of pages, you can do this :
import { Login } from `LoginContainerFile`;
import { Comp1} from `Comp1ContainerFile`;
import { Comp2} from `Comp2ContainerFile`;
export { Login, Comp1, Comp2 };
Good luck and hope it resolves your problem.

Related

Was Form.create() from antd replaced?

i am trying to create a login page in react using antd. I found a tutorial for doing this,but i belive that it is outdated, because it gives an error. I read on a forum that form.create() is not available anymore, but i don't know how to replace it.Here is my code:
import { Form, Icon, Input, Button, Spin } from 'antd';
import { connect } from 'react-redux';
import { NavLink } from 'react-router-dom';
import * as actions from '../store/actions/auth';
const FormItem = Form.Item;
const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />;
class NormalLoginForm extends React.Component {
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
this.props.onAuth(values.userName, values.password);
this.props.history.push('/');
}
});
}
render() {
let errorMessage = null;
if (this.props.error) {
errorMessage = (
<p>{this.props.error.message}</p>
);
}
const { getFieldDecorator } = this.props.form;
return (
<div>
{errorMessage}
{
this.props.loading ?
<Spin indicator={antIcon} />
:
<Form onSubmit={this.handleSubmit} className="login-form">
<FormItem>
{getFieldDecorator('userName', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
)}
</FormItem>
<FormItem>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
)}
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit" style={{marginRight: '10px'}}>
Login
</Button>
Or
<NavLink
style={{marginRight: '10px'}}
to='/signup/'> signup
</NavLink>
</FormItem>
</Form>
}
</div>
);
}
}
const WrappedNormalLoginForm = Form.create()(NormalLoginForm);
const mapStateToProps = (state) => {
return {
loading: state.loading,
error: state.error
}
}
const mapDispatchToProps = dispatch => {
return {
onAuth: (username, password) => dispatch(actions.authLogin(username, password))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(WrappedNormalLoginForm);
When i try to run it, i get an error that says:
TypeError: _antd.Form.create(...) is not a function
How can i rewrite the code in order to make it run?
AntD has removed Form.create in v4 and you can replace the above code with the modified API structure like
class NormalLoginForm extends React.Component {
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
this.props.onAuth(values.userName, values.password);
this.props.history.push('/');
}
});
}
render() {
let errorMessage = null;
if (this.props.error) {
errorMessage = (
<p>{this.props.error.message}</p>
);
}
const { getFieldDecorator } = this.props.form;
return (
<div>
{errorMessage}
{
this.props.loading ?
<Spin indicator={antIcon} />
:
<Form onSubmit={this.handleSubmit} className="login-form">
<FormItem name='userName' rules={[{ required: true, message: 'Please input your username!' }]}>
<Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
</FormItem>
<FormItem name="password" rules={[{ required: true, message: 'Please input your Password!' }]}>
<Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit" style={{marginRight: '10px'}}>
Login
</Button>
Or
<NavLink
style={{marginRight: '10px'}}
to='/signup/'> signup
</NavLink>
</FormItem>
</Form>
}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
loading: state.loading,
error: state.error
}
}
const mapDispatchToProps = dispatch => {
return {
onAuth: (username, password) => dispatch(actions.authLogin(username, password))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(NormalLoginForm);
Please see the migration guidelines for more details
I think you are using Antd v4.*. Form.create({}) is no more in latest version, so you have to your code as follow to make it working. V4 has. major changes so you have to go through migration guidelines
import { Form, Input, Button, Spin } from 'antd';
import { LoadingOutlined, UserOutlined, LockOutlined } from "#ant-design/icons";
import { connect } from 'react-redux';
import { NavLink } from 'react-router-dom';
import * as actions from '../store/actions/auth';
const FormItem = Form.Item;
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} />;
class NormalLoginForm extends React.Component {
handleFinish = (values) => {
this.props.onAuth(values.userName, values.password);
this.props.history.push('/');
}
render() {
let errorMessage = null;
if (this.props.error) {
errorMessage = (
<p>{this.props.error.message}</p>
);
}
return (
<div>
{errorMessage}
{
this.props.loading ?
<Spin indicator={antIcon} />
:
<Form onFinish={this.handleFinish} className="login-form">
<FormItem name="userName" rules={[{ required: true, message: 'Please input your username!' }]}>
<Input prefix={<UserOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
)}
</FormItem name="password" rules={[{ required: true, message: 'Please input your Password!' }]}>
<FormItem>
<Input prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
)}
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit" style={{marginRight: '10px'}}>
Login
</Button>
Or
<NavLink
style={{marginRight: '10px'}}
to='/signup/'> signup
</NavLink>
</FormItem>
</Form>
}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
loading: state.loading,
error: state.error
}
}
const mapDispatchToProps = dispatch => {
return {
onAuth: (username, password) => dispatch(actions.authLogin(username, password))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(NormalLoginForm);

Disable form.item 1 if form.item 2 is filled in

I want to hide form.item 1 if form.item 2 is filled in and the other way around.
I want to do it for the following code but i cant find the solution to this.
<Form.Item label="Url">
{getFieldDecorator('url')(<Input/>)}
</Form.Item>
<Form.Item label="Standaard Urls" >
{getFieldDecorator('url_id', {})(this.getSelectUrls())}
</Form.Item>
Basically i want too know how i can hide 1 form.item and the rest i can do myself
You need to use onFieldsChange of Form.create, that keeps your Form uncontrollable which is the cleanest way.
Wrap your Form with a state, pass it and use onFieldsChange like so:
const FormContainer = () => {
const [isVisible, setIsVisible] = useState(true);
const onFieldsChange = (_, changedFiels) => {
const { password } = changedFiels;
if (password) {
console.log(`Now changing ${password.name}`);
setIsVisible(false);
}
};
const ValidatedFields = Form.create({ onFieldsChange })(MyForm);
return <ValidatedFields isVisible={isVisible} />;
};
Warning: You need to figure how you want to "remove" the form field, it depends on if you need its state or not, for this you can use display CSS property:
// Will unmount the item and lose it state
{ isVisible && <Form.Item>...}
// Will keep the state and hide the item
<Form.Item style={{ display: isVisible ? 'auto' : 'none' }}>...
Full code:
In this example, you can write in the password field and it will hide other forms items:
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { Input, Form, Icon } from 'antd';
import 'antd/dist/antd.css';
import './index.css';
const FormContainer = () => {
const [isVisible, setIsVisible] = useState(true);
const onFieldsChange = (_, changedFiels) => {
const { password } = changedFiels;
if (password) {
console.log(`Now changing ${password.name}`);
setIsVisible(false);
}
};
const ValidatedFields = Form.create({ onFieldsChange })(MyForm);
return <ValidatedFields isVisible={isVisible} />;
};
const MyForm = ({ form, isVisible }) => {
const { getFieldDecorator, validateFields } = form;
const handleSubmit = e => {
e.preventDefault();
validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
};
return (
<Form onSubmit={handleSubmit} className="login-form">
{isVisible && (
<Form.Item>
{getFieldDecorator('username', {
rules: [{ required: true, message: 'Please input your username!' }]
})(
<Input
prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
placeholder="Item 1"
/>
)}
</Form.Item>
)}
<Form.Item style={{ display: isVisible ? 'auto' : 'none' }}>
{getFieldDecorator('username2', {
rules: [{ required: true, message: 'Please input your username!' }]
})(
<Input
prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
placeholder="Item 2"
/>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }]
})(
<Input
prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />}
type="password"
placeholder="Type here to hide other forms"
/>
)}
</Form.Item>
</Form>
);
};
ReactDOM.render(<FormContainer />, document.getElementById('root'));
const [showItem1, setShowItem1] = useState(true);
const [showItem2, setShowItem2] = useState(true);
onKeyPress = {() => {setShowItem1(true); setShowItem1(false); }}
onKeyPress = {() => {setShowItem1(false); setShowItem1(true); }}
{
showItem1 &&
<Form.Item label="Url">
{getFieldDecorator('url')(<Input/>)}
</Form.Item>
}
{
showItem2 &&
<Form.Item label="Standaard Urls" >
{getFieldDecorator('url_id', {})(this.getSelectUrls())}
</Form.Item>
}

Form async-validator not rendering

I am trying to make a simple form.
I am able to get all valid data if they are inputted and receive errors on the console, if they are not:
async-validator: ["username is required"]
async-validator: ["passwordis required"]
But the errors are not rendering.
Parent
const HomePage = () => (
<Layout className="layout" style={{ minHeight: '100vh' }}>
<Header>Teste</Header>
<Content className={_s.Content}>
<LoginForm />
</Content>
<Footer style={{ textAlign: 'center' }}>React Node Boilerplate by Igor Cesar</Footer>
</Layout>
);
export default HomePage;
Form
class LoginForm extends React.Component {
handleSubmit = e => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
};
render() {
const { getFieldDecorator } = this.props.form;
return (
<Form onSubmit={this.handleSubmit} className={_s.loginForm}>
<Form.Item>
{getFieldDecorator('username', {
rules: [{ required: true, message: 'Please input your username!' }]
})(
<Input
prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
placeholder="Username"
/>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }]
})(
<Input
prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />}
type="password"
placeholder="Password"
/>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('remember', {
valuePropName: 'checked',
initialValue: true
})(<Checkbox>Remember me</Checkbox>)}
<a className={_s.loginFormForgot} href="/">
Forgot password
</a>
<Button type="primary" htmlType="submit" className={_s.loginFormButton}>
Log in
</Button>
Or register now!
</Form.Item>
</Form>
);
}
}
const WrapperLoginForm = Form.create()(LoginForm);
export default WrapperLoginForm;
In order to help people who will reach this page in the future:
The author reported the bug to antdesign and a solution was found.
This was a problem with lodash-webpack-plugin, and the required change is in webpack.config.js. Turns out LodashModuleReplacementPlugin() should receive {paths: true} as a parameter, and the problem's gone.
module.exports = {
//... rest of your webpack config
plugins: [
//... rest of your plugins
new LodashModuleReplacementPlugin({paths: true}),
],
}

Redux not reaching the action

Here is the login.js file
import {Form, Icon, Input, Button} from 'antd';
import React from 'react'
import axios from 'axios'
import {connect} from 'react-redux'
import {loading} from '../actions/authenticationActions'
class Login extends React.Component {
handleSubmit = (e) => {
e.preventDefault();
return this.props.onloading;
};
render() {
const { getFieldDecorator } = this.props.form;
return (
<div className={'ant-col-12 ant-col-offset-6'} style={{ display: 'inline-flex', justifyContent: 'center', alignItems: 'center', height: "100vh"}}>
<Form onSubmit={this.handleSubmit} className="login-form" style={{width: "300px"}}>
<Form.Item>
{getFieldDecorator('userName', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
)}
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" className="login-form-button" style={{width: "100%"}}>
Log in
</Button>
</Form.Item>
</Form>
</div>
);
}
}
const WrappedLogin = Form.create({ name: 'normal_login' })(Login);
const mapActionsToProps = {
onloading: loading
};
export default connect(null, mapActionsToProps)(WrappedLogin);
and here is the Actions file:
import {LOADING} from "../utils/ActionTypes";
export function loading() {
console.log("action received");
return {
type: LOADING
}
}
also here is the Reducers file:
import {LOADING} from "../utils/ActionTypes";
const initialState= [{
Authorized: false,
user: null,
token: null,
loading: false
}];
export default function authenticationReducer(state = initialState, action) {
switch (action.type) {
case LOADING:
return console.log("loading....");
default:
return state;
}
}
and finally the Store file:
import {combineReducers, createStore, compose} from "redux";
import authenticationReducer from "../reducers/authenticationReducer";
const store = createStore(authenticationReducer, compose(
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
));
export default store;
hi, I have just started learning redux and I have this issue where as you can see in the actions file there is a console message the problem is I'm not reaching that point and I don't know why any help is appreciated...
You're not calling your action this.props.onloading anywhere in your code. Calling it in the method will dispatch the corresponding action.
handleSubmit = (e) => {
e.preventDefault();
this.props.onloading()
};

Getting Uncaught TypeError: Super expression must either be null or a function, not undefined

Below is my loginForm.js from where I suspect the error is originating:-
import { Form, Icon, Input, Button, Checkbox } from 'antd';
const FormItem = Form.Item;
import React, { Component } from 'react';
class NormalLoginForm extends Component {
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
}
render() {
const { getFieldDecorator } = this.props.form;
return (
<Form onSubmit={this.handleSubmit} className="login-form">
<FormItem>
{getFieldDecorator('userName', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
)}
</FormItem>
<FormItem>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
)}
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit" className="login-form-button">
Log in
</Button>
Or register now!
</FormItem>
</Form>
);
}
}
const WrappedNormalLoginForm = Form.create()(NormalLoginForm);
export default WrappedNormalLoginForm;
Below is my main component file where I load handle routing:-
import React, { Component } from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import WrappedNormalLoginForm from './loginForm'
export default class App extends Component {
render() {
return (
<div className="container">
<BrowserRouter>
<div>
<Route exact path="/" component={WrappedNormalLoginForm} />
</div>
</BrowserRouter>
</div>
);
}
}
I am unable to resolve this issue. I have extended using capital C which was mentioned as a fix for many of the questions asked regarding this.

Resources