Change Select (drop down) selection on state change within react component - javascript

I have a dropdown I want to be pre-selected when the data is available. However there appears to be no real chance for that?
Since I am waiting for a change in state for a particular value using that value as the value= causes the selections to be unselectable, while using it as a defaultValue= causes the UI to not recognize the value unless a change to the element has been made meaning if the user decides to go with the default choice it wouldn't be passed up the to the API I am trying to pass it up to.
Is there a way to dynamically change a select box after the dom is ready after the components mounted and when a state is changed?

It's a bit difficult without seeing the code, but have you tried setting the value into the React component's state and rendering that instead? You can also read the state's value instead of the DropDown's.
getInitialState: function () {
return {
dropDownSelection: "some default value"
};
},
handleSelectionChanged: function (e) {
this.setState({
dropDownSelection: e.target.value
});
},
render: function () {
return (
//...
<select className="form-control" value={this.state.dropDownSelection} onChange={this.handleSelectionChanged}>
//...
</select>
);
}

Related

Using HTMLFormElement.reset() with Downshift and react-hook-form

I'm using DownshiftJS to create an Autocomplete component using the useCombobox hook. It's all going well and testing with react-hook-form. Unfortunately, I've hit a problem where the reset function available within react-hook-form, which fires the HTMLFormElement.reset() method, does not trigger any state/input change within the Downshift component.
This means that when a user selects an item from the list (which triggers an event in the Autocomplete), clicks the reset button and then clicks the input again, the list is filtered to just the previously selected item. This is because the selected item is stored within a selectedItem internal state.
How can I get the reset method to trigger a change within Autocomplete component and clear the selectedItem state?
I've isolated the issue here.
You can use React.useEffect to detect if the user hits the reset button and reset the selected items accordingly in your Autocomplete component
const [inputItems, setInputItems] = useState(options);
const {
inputValue,
...
} = useCombobox({
items: inputItems,
...
});
React.useEffect(() => {
if (!inputValue) {
// user resets value. Reset selected option
setInputItems(options);
}
}, [inputValue, options, setInputItems]);
Live Demo

How do I prevent Chrome from saving / caching the chosen option in a <select> element?

Inside of my React application, I have the following JSX code:
import React, { Component } from 'react'
export default class CategoryForm extends Component {
render() {
return (
<div className="category-form">
<label>
Category
<select value={this.props.selectedCategory} id="selectedCategory" onChange={this.props.handleChange}>
<option value="Best">Best</option>
<option value="Controversial">Controversial</option>
<option value="Hot">Hot</option>
<option value="New">New</option>
<option value="Rising">Rising</option>
<option value="Top">Top</option>
</select>
</label>
</div>
)
}
}
It's a simple element with elements as children. The default value is initialized as, "Best". When the page is initially visited or refreshed, the value contained in the element reverts to "Best" (as expected), but when a user navigates away from the page and presses the back button, the element retains whatever value was previously selected. How do I prevent this behavior? I'm trying to avoid forcing a re-render.
EDIT: I made the mistake of omitting code because I thought it would make the question more simple. Here's the state that I'm initializing in the constructor of the component, as well as the child component being created in the parent component. I modified my code according to the React documentation (and HMR) on controlled components, and I am still having the same problem.
export default class App extends Component {
constructor(props) {
super(props)
this.state= {
selectedCategory: "Best",
minScore: -100,
numPosts: 25,
subreddit: "",
searchTerm: "",
timeframe: "hour",
postArray: [],
animationTracker: false,
selectedForm: "Category",
}
this.handleChange = this.handleChange.bind(this);
this.backendCall = this.backendCall.bind(this);
this.changeForm = this.changeForm.bind(this);
}
\\ handle change method
handleChange(event) {
// dynamically set the key of the setstate object to be equal to the id of the specific form
let selectedCategory = event.target.id;
this.setState({[selectedCategory]: event.target.value});
}
\\ later on...
{this.state.selectedForm === "Category"
? <CategoryForm selectedCategory={this.state.selectedCategory} handleChange={this.handleChange.bind(this)}/>
: <TermForm handleChange={this.handleChange.bind(this)}
searchTerm={this.state.searchTerm} timeframe={this.state.timeframe} />
}
ScreenshotHere is a screenshot showing the problem in action. After pressing the to back button, the state is reinitialized (which should change the value to "Best"), but the value of my element remains at whatever the user selected before navigating away from the page (in this case, "Hot"). In addition, if I modify the fields below (Minimum score and number of posts), then navigate away from the page, then press the back button, those fields follow the expected behavior and revert to the default state.
We might need to see more of your code.
I'm guessing that the handlechange() function sets the local state to the selected option. You'll need to clear that state to revert to the default option.

React - How to trigger animation if value of div/span is updated?

I have the following problem: I'm working on a react app and I have a div, which contains multiple span-tags. The value of these span tags are dynamically changed and whenever a change of these values occured, I'd like to trigger an animation. While the values are changing without any problems, the animation only triggers during the first initial load. Afterward it fails to trigger. Is there any way I can tell or force my app to trigger the animation when the value of the div-container is changed?
Here is a shortened example of my code:
<div className="animation">
<span>{value}</span>
<span>{value2}</span>
</div>
I don't know how your values are structured but here's my recommendation
Make an animated span component and get the value as a prop.
Then whenever that value changes, The span component will re-render and you will see the animation.
Put your value and value2 in to the state, and then change the state value and your component will re-render.
Like this:
constructor() {
super();
this.state = {
value: 'animation',
value2: 'animation'
};
}
changeAnimation() {
this.setState({
value: 'animation2',
value2: 'animation2'
})
}

React widget Combobox not updating onFocus with Reduxform

I actually have 2 combobox (react-widgets) on my reduxform.
My first combobox works perfectly because I fetch my datas onChange.
But when I focus the second one I want my data loaded in it depending on the value of the first one.
The problem is : I have data in the render when I console.log it but the component not rerendering. I have to type something in the field to see my data, it's like only the onchange trigger the rerendering.
Field in the form:
<Field
component={HouseComp}
name="house"
currenthouses={currenthousesValue}
onFocus={getHouses(props)}
{...props}
/>
My component render:
<Combobox id="house"
data={currenthouses}
{...input}
/>
the getHouses function is a fetch returning something like :
props.dispatch(change('form', 'currenthouses',data))
the currenthousesValue is from a selector:
const currenthousesValue = selector(state, 'currenthouses');
I tried to force the update by using componentDidUpdate but even if I see the call of my render function the UI is not refreshing.
I also tried to load the data on "onBlur" from the first one but same result.
I am new to React. But I faced a similar issue in React. In your case when the value of first combo box changes, The value of data attribute of second form also changes. But your second combobox is not re-rendering may be becuase it is not subscribed to componentWillReceiveProps event.
Something like this(taken from my code):
componentWillReceiveProps(nextProps) {
this.setState({
groups: nextProps.groups,
invoices_count: nextProps.groups.length
});
}

How do I programatically fill input field value with React?

I have a modal with some input fields. I can easily pass the data automatically with the user typing an input, using onChange function in the input field, as
<Input onChange={this.props.store.handleCategoryChange} type="text" />
and .. (Using a mobx store, irellevant though)
#observable categoryValue;
#action handleCategoryChange = (e, data) => {
this.categoryValue = data.value;
e.preventDefault();
};
However, I want to add a function where the user can pre-fill this with information elsewhere in the application. I have the data to pre-fill the input fields with, but I can't figure out how do actually input it programatically, without the user doing it?
I need to invoke the above handleCategoryChange function. But my variable would be equal to data.value .. Which presents a problem! Invoking this function by myself isn't possible, because I won't have the event e nor a value called data.value as I will "just" pass in a variable by itself.
What's the right way to programatically fill an input field automatically in React, using variables elsewhere? I need to invoke the onChange function somehow, but the input values will be different..
Use controlled component for this situation, define a value property of input element like this:
<Input value={variable_name} ....
Whenever you will update that variable, automatically that value will get populated in input element.
Now you can populate some default value by assigning a value to variable_name and user can update that value by onChange function.
As per DOC:
An input form element whose value is controlled by React in this way
is called a "controlled component".
Pass in the value property for input:
<input type="text" value={this.state.value} onChange={(e) => {this.setState({value: e.target.value })}/>
you can use the controlled component and pass the value to it.
<input type="text" value{this.state.value}
onChange={()=> {this.setState({value:e.target.value })}}
Good question. I'm having the same issue, and just found a solution.
The problem is that:
You can't just use the default state of the modal component to set the initial input value, because the modal renders one time within the parent component (starting off invisible), so the default state of the Modal wont keep up with any changes to the 'pre-filled' info in the store that the inputs within the modal require access to.
You can't use the value attribute of the input to reference some redux store prop, since this is needed to reference the onChange function so the user can make changes to that pre-filled info.
And, you can't use the onChange function to set the initial value, because it is required to update the local state with the users changes - not set an initial value. Anyway, this requires the user to click on something, and you want the modal inputs to be pre-populated before the user does anything as soon as the modal opens...
So. What we need is to update these input fields every time the Modal attribute isModalOpen (or whatever you are using) changes.
(ie, pre-populate the fields when the Modal is opened).
Again, note that opening the Modal is not RENDERING the modal, it was already rendered, once, and has sat there being invisible until that isModalOpen attribute changed to true.
The Solution:
Step 1: make a handler function in the Modal component that prefills the inputdata by updating the local state of the Modal component. Mine looks like this :
handlePreFillModalInputsOnOpen = () => {
this.setState(() => ({
orthForm: this.props.matchLexUnit['orthForm'],
orthVar: this.props.matchLexUnit['orthVar'],
oldOrthForm: this.props.matchLexUnit['oldOrthForm'],
oldOrthVar: this.props.matchLexUnit['oldOrthVar'],
source: this.props.matchLexUnit['source'],
namedEntityCheck: this.props.matchLexUnit['namedEntityCheck'],
styleMarkingCheck: this.props.matchLexUnit['styleMarkingCheck'],
artificialCheck: this.props.matchLexUnit['artificialCheck'],
error: ''
}));
};
Step 2: Make that function fire ONLY when the isOpen attribute of the modal changes from false to true.
(This is the meat of your problem I think).
Use the lifecycle method componentDidUpdate. This will execute every time the props of the modal change.
componentDidUpdate(prevProps) {
if (this.props.isModalOpen === true && prevProps.isModalOpen === false) {
this.handlePreFillModalInputsOnOpen();
}
}
Watch out
make sure that you have a conditional in componentDidUpdate, otherwise you can run into infinite-loop/performance issues
if you have the possibility of null values icoming in as the prefilled input info, make a null-check so that they will not be passed into the local state.
Hope this helps :)
How to Programmatically Prefill, Fill or Update input fields value in React or useState Hooks?
Firstly - Get and define the data from database
const **yourData** = isDataFromDatabase;
or if the data is stored in Redux, then...
const **yourData** = useSelector(isDataFromDatabase);
Secondly - append it as the default value of a useState hook
const [isDataValue, setIsDataValue] = useState(**yourData**);
Thirdly - create a function to watch and Update the changes made by the user to your data value and set it to the useState hook created above
/** handles Your Data Value */
const handleDataValue = (text) => {
setIsDataValue(text);
};
Lastly - in your input tag, use the useState State as the "Value" parameter so it can be updated with the onChange function
<input
className="css"
id="myDataInput"
type="text"
value={isDataValue}
placeholder={isDataValue}
onChange={(e) => handleDataValue(e.target.value)}
/>
Now when you load the component, the prefilled value will be shown and can be updated in the HTML Input field.
That's All.

Categories

Resources