how to get user input from antd Input.Password? - antd

I am trying to get user input from antd input.password field. Is it possible?
I didnt see any information on antd docs. I wonder if its possible
I am expecting a string for user input.password since i'll be saving them into local storage

You can always use onChange method like onChange={e => console.log(e.target.value) }
CodeSandbox: https://codesandbox.io/s/5283xn4vo4
import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Input, Button } from "antd";
class PasswordToLocalStorage extends React.Component {
state = {
password: undefined
};
render = () => {
return (
<React.Fragment>
<Input.Password
onChange={e => this.setState({ password: e.target.value })}
placeholder="Enter Password"
/>
<Button
onClick={() => {
if (this.state.password) {
localStorage.setItem("password", this.state.password);
alert("saved to local storage: " + localStorage.password);
} else {
alert("There is no password to save");
}
}}
>
Save to localStorage
</Button>
</React.Fragment>
);
};
}
ReactDOM.render(
<PasswordToLocalStorage />,
document.getElementById("container")
);

Related

react-hook-form custom resolver only checking after submit

I'm building an abstract form component with react-hook-form and Yup for validation. The form works, and validation works, but only after the submit button is pressed.
It's on codesandbox, but ...
import React, { cloneElement } from "react";
import "./styles.css";
import { Controller, FormProvider, useForm } from "react-hook-form";
import { yupResolver } from "#hookform/resolvers/yup";
import { string as yupString, object as yupObject } from "yup";
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
TextField
} from "#mui/material";
let renderCount = 0;
export const FormContent = ({ content }) => {
return content.map((item, i) => {
const name = item.component.props.name;
return (
<Controller
key={name + "_" + i}
name={name}
defaultValue=""
render={({ field, fieldState: { error }, formState: { isDirty } }) => {
return cloneElement(item.component, {
...field,
error: isDirty && !!error,
helperText: isDirty && error?.message,
FormHelperTextProps: { error: true }
});
}}
/>
);
});
};
export default function App() {
renderCount++;
const usernameInput = {
validation: yupString().required("Username is required"),
component: (
<TextField required label="Username" name="username" type="text" />
)
};
const passwordInput = {
validation: yupString().required("Password is required"),
component: <TextField required label="Password" name="password" />
};
const content = [usernameInput, passwordInput];
let validationSchema = yupObject().shape({});
// construct schema
content.forEach((item) => {
validationSchema = validationSchema.concat(
yupObject().shape({
[item.component.props.name]: item.validation
})
);
});
const methods = useForm({
resolver: yupResolver(validationSchema)
});
const onFormSubmit = (data) => {
console.log(data);
};
return (
<Dialog open>
<Box>Render Count: {renderCount}</Box>
<FormProvider {...methods}>
<Box component="form" onSubmit={methods.handleSubmit(onFormSubmit)}>
<DialogContent>
<FormContent content={content} />
</DialogContent>
<DialogActions>
<Button
type="submit"
fullWidth
name="login"
variant="contained"
color="primary"
size="large"
>
Login
</Button>
</DialogActions>
</Box>
</FormProvider>
</Dialog>
);
}
If you type some data in the fields, and then erase the data without pressing the button, nothing happens. If you leave the fields empty and press the button, it gives the native component error message for required (i.e., it doesn't do the Yup resolving). But, if you enter some data, press the button, and then erase the data, then the Yup validation kicks in. How do I make it work before the button is pressed?
You need to remove required prop from input components because otherwise native html validation will kick in.
And if you want start validation before pressing submit button you need to use some other mode for form, for example:
const methods = useForm({
resolver: yupResolver(validationSchema),
mode: 'onChange' // or 'onBlur' for example
});
Codesandbox
More info in the docs

Problem with first try simple Relay/React example

I read relay official docs and followed example.
Now, I slightly change it for practice. I replaced load query with useQueryLoader
but result is, Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
I think it is related to loadRepoQuery() part, but without it, TypeError: null is not an object (evaluating 'preloadedQuery.fetchKey') occurs.
I think it's due to my misunderstanding. Please help me.
// App.js
import './App.css';
import graphql from 'babel-plugin-relay/macro';
import {
usePreloadedQuery,
useQueryLoader,
} from 'react-relay/hooks';
// Define a query
const RepositoryNameQuery = graphql`
query AppRepositoryNameQuery {
repository(owner: "facebook", name: "react") {
name
}
}
`;
function RepoRenderer() {
const [repoQueryRef, loadRepoQuery] = useQueryLoader(RepositoryNameQuery);
loadRepoQuery();
return (
<Repo preloadedQuery={repoQueryRef}/>
)
}
function Repo(props) {
const data = usePreloadedQuery(RepositoryNameQuery, props.preloadedQuery);
return (
<div className="App">
<header className="App-header">
<p>{data.repository.name}</p>
</header>
</div>
);
}
export default function App() {
return (
<RepoRenderer/>
);
}
//
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom';
import { RelayEnvironmentProvider } from 'react-relay';
import relayEnvironment from './relayEnvironment';
import App from './App';
import './index.css';
ReactDOM.render(
<React.StrictMode>
<RelayEnvironmentProvider environment={relayEnvironment}>
<Suspense fallback={'Loading...'}>
<App/>
</Suspense>
</RelayEnvironmentProvider>
</React.StrictMode>,
document.getElementById('root')
);
I kind of solve this problem. Here's code snippet for newbie like me.
See this too.
// index.js
ReactDOM.render(
<RelayEnvironmentProvider environment={relayEnvironment}>
<Suspense fallback={'Loading...'}>
<App />
</Suspense>
</RelayEnvironmentProvider>,
document.getElementById('root')
);
//app.js
import React ,{ useCallback } from 'react';
import './App.css';
import graphql from 'babel-plugin-relay/macro';
import {
usePreloadedQuery,
useQueryLoader,
} from 'react-relay/hooks';
// Define a query
const RepositoryNameQuery = graphql`
query AppRepositoryNameQuery {
repository(owner: "yujong-lee", name: "taggy") {
name
}
}
`;
function Repo({queryRef, refetch}) {
const data = usePreloadedQuery(RepositoryNameQuery, queryRef);
return (
<div className="App">
<header className="App-header">
<p>{data.repository.name}</p>
</header>
</div>
);
}
function App() {
const [repoQueryRef, loadRepoQuery] = useQueryLoader(RepositoryNameQuery);
const refetch = useCallback(() => {
loadRepoQuery();
}, [loadRepoQuery])
if(repoQueryRef !== null) {
return <Repo queryRef={repoQueryRef} refetch={refetch}/>
}
return <button type='button' onClick={() => refetch()}>Fetch</button>
}
export default App;

React ant design typescript form validation not working

I used react typescript project to ant design and i used this ant design form validation, but its not working correctly, anyone know how to fix that issue?
Thanks
git a this error
index.tsx?789d:32 Uncaught TypeError: Cannot read property
'getFieldDecorator' of undefined
import * as React from "react";
import { Input, Form, Icon, Button, } from "antd";
import 'antd/dist/antd.css';
import "./style.css";
export class Registerform extends React.Component<any> {
handleSubmit = (e:any) => {
e.preventDefault();
this.props.form.validateFieldsAndScroll((err:any, values:any) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
};
render() {
const { getFieldDecorator } = this.props.form;
return (
/* Start add bulk upload form*/
<div className="remindersform-section">
<Form onSubmit={this.handleSubmit}>
<Form.Item
label={
<span>
Nickname
<Icon type="question-circle-o" />
</span>
}
>
{getFieldDecorator('nickname', {
rules: [{ required: true, message: 'Please input your nickname!', whitespace: true }],
})(<Input />)}
</Form.Item>
<Form.Item >
<Button type="primary" htmlType="submit">
Register
</Button>
</Form.Item>
</Form>
</div>
);
}
}
Because default form props are not assigned with their types, antd provided a solution for it, Try like below
import * as React from "react";
import { FormComponentProps } from "antd/es/form";
import { Input, Form, Icon, Button, } from "antd";
import 'antd/dist/antd.css';
interface UserFormProps extends FormComponentProps {
form: any;
}
class Registerform extends React.Component<UserFormProps> {
handleSubmit = (e:any) => {
e.preventDefault();
this.props.form.validateFieldsAndScroll((err:any, values:any) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
};
render() {
const { getFieldDecorator } = this.props.form;
return (
/* Start add bulk upload form*/
<div className="remindersform-section">
<Form onSubmit={this.handleSubmit}>
<Form.Item
label={
<span>
Nickname
<Icon type="question-circle-o" />
</span>
}
>
{getFieldDecorator('nickname', {
rules: [{ required: true, message: 'Please input your nickname!', whitespace: true }],
})(<Input />)}
</Form.Item>
<Form.Item >
<Button type="primary" htmlType="submit">
Register
</Button>
</Form.Item>
</Form>
</div>
);
}
}
const WrappedForm = Form.create<UserFormProps>({})(Registerform);
export default WrappedForm;

Why is my tracks array empty in my presentational component?

I've been working on this bug for a few hours now, and I think I've narrowed it down to these pieces of code:
// my track detail container:
import { connect } from 'react-redux';
import TrackDetail from './track_detail';
import { selectTracksFromPlaylist } from '../../reducers/selectors';
const mapStateToProps = (state, { playlistId }) => ({
tracks: selectTracksFromPlaylist(state, state.entities.playlists[playlistId])
});
export default connect(mapStateToProps)(TrackDetail);
// my track detail presentational component:
import React from 'react';
import TrackIndexItem from './track_index_item';
const TrackDetail = ({ tracks }) => (
<ul>
{ tracks.map(track => <TrackIndexItem key={track.id} track={track} />) }
</ul>
);
export default TrackDetail;
// my selector that I'm using to select all tracks from a playlist:
export const selectTracksFromPlaylist = (state, playlist) => (
playlist.track_ids.length > 0 ? playlist.track_ids.map(id => state.entities.tracks[id]) : []
);
// the component that's rendering my TrackDetail:
import React from 'react';
import { Route } from 'react-router-dom';
import TrackDetail from '../track/track_detail_container';
class PlaylistDetail extends React.Component {
componentDidMount() {
this.props.requestSinglePlaylist(this.props.match.params.playlistId);
}
render() {
const { playlist } = this.props;
if (!playlist) return null;
return (
<div className="playlist-detail-container">
<div className="playlist-detail-header">
<p>Playlist</p>
<h1>{ playlist.title }</h1>
<p>
Created by <span>{playlist.user}</span> • {playlist.track_ids.length} songs
</p>
</div>
<div className="playlist-detail-tracks">
<TrackDetail playlistId={ playlist.id } />
</div>
</div>
);
}
}
export default PlaylistDetail;
This happens every time I try accessing the page normally (without physically doing a refresh; if I refresh the screen after this error pops up, it works):
Uncaught TypeError: Cannot read property 'id' of undefined

Integration in React with Ruby on Rails.

I was following the instructions from a tutorial about integrating React with Ruby on Rails. I installed webpack 'webpacker', 'haml' and 'ransack'. All my backend code is working right now.
I created a view to point to my jsx files. On a Hello World attempt, the jsx its correctly rendered. My problem is after that.
I created a JobOffers.jsx file. So, on my dashboard file i pointed to this other one.
This is my dashboard.jsx
import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
import JobOffers from './JobOffers'
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<JobOffers/>
)
})
And this is my JobOffer.jsx
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class JobOffers extends Component {
constructor(props) {
super(props);
this.state = {
term: '',
autoCompleteResults: [],
itemSelected: {},
showItemSelected: false
};
$.getJSON('/search?q=' + this.state.term)
.then(response => this.setState({ autoCompleteResults: response.items }))
}
getAutoCompleteResults(e){
this.setState({
term: e.target.value
}, () => {
$.getJSON('/search?q=' + this.state.term)
.then(response => this.setState({ autoCompleteResults: response.items }))
});
}
render(){
let autoCompleteList = this.state.autoCompleteResults.map((response, index) => {
return <div key={index}>
<h2>{response.title}</h2>
<p>{response.description }</p>
</div>
});
return (
<div>
<input ref={ (input) => { this.searchBar = input } } value={ this.state.term } onChange={ this.getAutoCompleteResults.bind(this) } type='text' placeholder='Search...' />
{ autoCompleteList }
</div>
)
}
}
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<JobOffers />,
document.body.appendChild(document.createElement('div')),
)
});
export default JobOffers;
When I go to the page, it renders for less then one second the right input, and then disappears. Anyone know what Im doing wrong here?
dashboard.jsx:
import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
import JobOffers from './JobOffers'
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<JobOffers/>,
document.body.appendChild(document.createElement('div')),
)
})
JobOffers.jsx:
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class JobOffers extends Component {
constructor(props) {
super(props);
this.state = {
term: '',
autoCompleteResults: [],
itemSelected: {},
showItemSelected: false
};
}
componentDidMount() {
$.getJSON('/search?q=' + this.state.term)
.then(response => this.setState({ autoCompleteResults: response.items }))
}
getAutoCompleteResults(e){
this.setState({
term: e.target.value
}, () => {
$.getJSON('/search?q=' + this.state.term)
.then(response => this.setState({ autoCompleteResults: response.items }))
});
}
render(){
let autoCompleteList = this.state.autoCompleteResults.map((response, index) => {
return <div key={index}>
<h2>{response.title}</h2>
<p>{response.description }</p>
</div>
});
return (
<div>
<input ref={ (input) => { this.searchBar = input } } value={ this.state.term } onChange={ this.getAutoCompleteResults.bind(this) } type='text' placeholder='Search...' />
{ autoCompleteList }
</div>
)
}
}
export default JobOffers;

Resources