I'm using react-calendar package on my react app. Placing <Calendar/> on the file gives the open calendar on the frontend.
But I want to display the calendar if the user clicks the input field:
<div className="form-group">
<label>Start Date</label>
<input type="text"/>
<Calendar style={{display: "none"}} />
</div>
I tried through inline style to hide the calendar component and change on click. But the calendar doesn't hide with inline css also.
Gone through documentation also but didn't find any help.
It will be best you create a wrapper component around your calendar and input. This way it manages its own showCalendar state and can be reused elsewhere.
import React, { useState } from "react";
import Calendar from "react-calendar";
const ReactCalendarDemo = ({ date, setDate }) => {
const [showCalendar, setShowCalendar] = useState(false);
const handleChange = value => {
setDate(value);
setShowCalendar(false);
};
return (
<div>
<input
value={date.toLocaleDateString()}
onFocus={() => setShowCalendar(true)}
/>
<Calendar
className={showCalendar ? "" : "hide"}
value={date}
onChange={handleChange}
/>
</div>
);
};
export default ReactCalendarDemo;
You pass in your current date value and its setter as props.
Then you can toggle display in your CSS style using the hide class
.react-calendar.hide {
display: none;
}
Related
I have a very simple react component with input:
const Search = ({ onchange, t }) => {
const [value, setValue] = useState('');
useEffect(() => {
console.log('value', value);
}, [value]);
return (
<div className={'user-search'}>
<input
placeholder={t('placeholder')}
className={'search-input'}
onChange={(e) => setValue(e.target.value)}
type="text"
/>
<div className={'search-icon'}>
<icon className={'icon'} size={'normal'} name="search" />
</div>
</div>
);
};
At the same time, I use a library with client components - most of them create a shadow-root in the DOM. Nevertheless, I can drop my components inside them via {children} or sometimes props.
Well, and I have a problem with this Search component: when I use it loosely anywhere in the project I get a console.log with "value" after typing something in the input. On the other hand, when I put it into the component with modal and accordion (from the client library) - input completely stops working and doesn't respond.
Could the non-functioning input have something to do with shadow-dom? Or do I need to provide more information?
Whenever I set a state in my React app, it clears out my inputs (check box, numbers). Here's a very barebones version that illustrates the issue.
import React, { useState } from "react";
export default function App() {
const [dummy, setDummy] = useState(false);
function handleMint() {
setDummy((dummy) => !dummy);
}
const MintBTN = () => (
<div>
<div>
<input className="form-control" type="number" max="20" min="1" />
<div>
<input type="checkbox" />
</div>
</div>
<div>
<button onClick={handleMint}>mint</button>
</div>
</div>
);
return <MintBTN />;
}
You can try it out yourself. Add numbers and click the check box and hit mint. Whamo-bamo, your inputs magically disappear.
https://codesandbox.io/s/friendly-buck-6g6oh?file=/src/App.js:0-499
I figure there's something I'm doing wrong that I just don't see yet. I need to be able to click the button or do an onChange event for the inputs without them clearing out. For some reason setting state is also making my page styles freak out. Not sure what's going on. Some of my key dependencies if those are helpful. Thanks.
"react": "^17.0.2",
"webpack": "^4.19.1"
Each time you set a state (setDummy), the component is rerendered and will reset you're inputs because they are uncontrolled. You need to make them controlled by using state hooks for those inputs.
import React, { useState } from "react";
export default function App() {
const [dummy, setDummy] = useState(false);
const [number, setNumber] = useState(0);
const [checked, setChecked] = useState(false);
function handleMint() {
setDummy((dummy) => !dummy);
}
return (
<div>
<div>
<input
className="form-control"
type="number"
max="20"
min="1"
value={number}
onChange={e => setNumber(e.target.value)}
/>
<div>
<input
type="checkbox"
checked={checked}
onChange={e => setChecked(e.target.checked)}
/>
</div>
</div>
<div>
<button onClick={handleMint}>mint</button>
</div>
</div>
);
}
Notice the value and checked properties. They are being set by the hook value on each render. Now, notice the onChange property. Each time you interact with the input it will update the hook value and rerender the component. By letting React manage the value and checked properties, it will save the values of the inputs in each hook.
Take a look at Controlled Components and State Hooks
Update
Removed MintBTN function as Nicholas Tower pointed out
You are creating the MintBTN component inside of your App component. This does not work. Every time App renders, you create a brand new type of component. It may have the same text as the previous one, but it's a new type, so react needs to unmount the old one, and mount a new one, which resets the values of stored in any dom elements, and resets any react state.
Instead, create the component once outside of app.
export default function App() {
const [dummy, setDummy] = useState(false);
function handleMint() {
setDummy((dummy) => !dummy);
}
return <MintBTN onClick={handleMint} />;
}
const MintBTN = ({ onClick }) => {
return (
<div>
<div>
<input className="form-control" type="number" max="20" min="1" />
<div>
<input type="checkbox" />
</div>
</div>
<div>
<button onClick={handleMint}>mint</button>
</div>
</div>
);
};
I have an app in MeteorJS, which makes use of React (I am ok with JavaScript, but am on a learning curve starting with React). The current search input makes use of the onchange function of the input box BUT this is actually not desired as this slows the app considerably - making requests every time the user types.
I basically want the input to be basic input and then have a button to trigger the search.
Inline code, for calling the searchinput where needed;
<div className="col-md-4 col-xs-12" style={disabledStyling.control}>
<SearchInput placeholder="Search" onChange={this.filterGames} value={filter} />
</div>
searchinput component;
import PropTypes from 'prop-types';
import Icon from '../Icon';
import Styles from './styles';
const SearchInput = ({ placeholder, value, onChange }) => (
<Styles.SearchInput className="SearchInput">
<Icon iconStyle="solid" icon="search" />
<input
type="text"
name="search"
className="form-control"
placeholder={placeholder}
value={value}
onChange={onChange}
/>
</Styles.SearchInput>
);
SearchInput.defaultProps = {
placeholder: 'Search...',
value: '',
};
SearchInput.propTypes = {
placeholder: PropTypes.string,
value: PropTypes.string,
onChange: PropTypes.func.isRequired,
};
export default SearchInput;
Hoping you all could help ;)
Basically what you need to do is use a state to store the value from the onChange event and later, on button click/form submit action you pass this value to the function that will actually fetch data.
Here is a small example on code sandbox where you can see this being applied both on a functional component and on a class component
lets assume your "wrapper" component is something like this:
const Form = () => {
const filterGames = (event) => {
// handle event and calls API
}
return (
<div className="col-md-4 col-xs-12" style={disabledStyling.control}>
<SearchInput placeholder="Search" onChange={filterGames} value={filter} />
</div>
)
}
What we need to do here, is basically adding the state and handle it without calling the API and a button to actually call the API.
const Form = () => {
const [inputValue, setInputValue] = useState('');
const filterGames = (event) => {
// handle event and calls API
}
// this will store the value locally on the state
const handleInputOnChange = (event) => {
setInputValue(event.target.value);
}
return (
<div className="col-md-4 col-xs-12" style={disabledStyling.control}>
<SearchInput placeholder="Search" onChange={handleInputOnChange} value={inputValue} />
<button type='submit' onClick={filterGames}>Submit</button>
</div>
)
}
ps: you can also wrap the input + button with a form and use form.onSubmit instead of button.onClick.
I developed a React App using Material-UI then I tried to create independent Components,
check the below independent components(<PanelDiv/>),
render() {
return (
<div className="panelDiv-component" style={{display:this.props.display}}>
<div className="panel-field-content">
<TextField
floatingLabelText={this.props.heading}
type={this.props.inputType}
value={this.props.value}
/>
{/* <input defaultValue className="form-control"></input>*/}
</div>
</div>
);
}
I tried to use the component like this,
<PanelDiv
heading='name'
inputType="text"
value={this.state.userData.name}
display={this.state.display[0]}
/>
But I can't update input field in this way.Also there is no error. How can i solve this? I want to update my input field.
Please check my input filed in the below image :
Because you are controlling the value of TextField by using value attribute but you are not updating the value by using onChange function, Since value of TextField is not changing so it becomes read only.
Solution:
Specify the onChange function with TextField and update the value inside that, Like this:
<TextField
floatingLabelText={this.props.heading}
type={this.props.inputType}
value={this.props.value}
onChange={this.props._change}
/>
Inside parent component:
_Change(event, value){
//update the value here
}
<PanelDiv
heading='name'
inputType="text"
value={this.state.userData.name}
_change={this._change}
display={this.state.display[0]}
/>
If you pass value as a prop to TextField you can't change that text!
On Material-UI official documentation they have used defaultValue="default val" as a prop.
So I used defaultValue as a prop! It worked fine for me!
<TextField
type="text"
defaultValue={this.props.val}
onChange={handleChange}
/>
Had the same error. I was not able to key in anything and it was because there was no name props included. example:
<TextField
type="email"
name='email'/>
Look at this example - https://jsfiddle.net/y857yeLq/
You should define a function, which is handles of text change and pass it to onChange property. In this example I used state for storing current text field value. I see, that you use props for that, but the principle is the same - function should update props in your case.
const { TextField, MuiThemeProvider, getMuiTheme } = MaterialUI;
class SliderExampleControlled extends React.Component {
state = {
value: '',
}
render() {
console.log(this.state);
return (
<div style={{width: '50%', margin: '0 auto'}}>
<TextField
hintText="Type here"
value={this.state.value}
onChange={(e) => this.setState(e.target.value)}
/>
</div>
);
}
}
const App = () => (
<MuiThemeProvider muiTheme={getMuiTheme()}>
<SliderExampleControlled />
</MuiThemeProvider>
);
ReactDOM.render(
<App />,
document.getElementById('container')
);
I was running into this problem as well and I needed the onClick function to take more than just the event I also needed it to take the row number because my state had an array representing the rows in a table. I was able to do that using this chunk of code
onChange={(e) => this.nameChange(e.target.value, row.row_num)}
then in my function called nameChange I was able to update the value
I am building a huge form which is made of atleast 50 inputs.
I have wrote a function in the form component that will save the value of the input to the form state:
PARENT FUNCTION
saveToState(details) {
const { company } = this.state;
company[details.part][details.element] = details.value;
this.setState({ company });
}
PASSING TO CHILD COMPONENT (INPUT)
<FieldInput
label="Name (as shown) *"
part="information"
element="displayName"
saveToState={this.saveToState}
/>
Here is the Input component:
import React, { Component } from 'react';
export default class FieldInput extends Component {
render() {
const { label, part, element, saveToState } = this.props;
return (
<div className="field">
<label>{label}</label>
<div className="ui input">
<input
type="text"
name={`${part}[${element}]`}
onChange={(e) => saveToState({
part,
element,
value: e.target.value
})}
/>
</div>
</div>
);
}
}
In result whenever I type something in the input It's taking it 200-300ms to really display what I wrote in the input, the state is getting updates instantly but whenever I type a character I set the new state of the parent form and update it which updates the whole component. The only way i found around it is to use saveToState within the parent component without passing it down. but that would require 1000's of line of code, Is there any way around this? Thanks!
There are alot of ways you can solve this problem. The easiest one and the fastest one is to use onBlur instead of onChange that way setState will happen not when you key pressing in the input but when the input loses focus.
import React, { Component } from 'react';
export default class FieldInput extends Component {
render() {
const { label, part, element, saveToState } = this.props;
return (
<div className="field">
<label>{label}</label>
<div className="ui input">
<input
type="text"
name={`${part}[${element}]`}
onBlur={(e) => saveToState({
part,
element,
value: e.target.value
})}
/>
</div>
</div>
);
}
}