Material-UI Select doesn't update after onChange - javascript

I've seen this problem about all around the web but nothing could come short of giving me a valid explanation.
I'm using Material-UI Select and the good ol' setState(...) from React (not hooks though)
My component is composed essentially of those lines :
class MyComponent extends Component {
exportOptions = ['CSV','SDF']
constructor(props) {
super(props);
this.state = {
[...]
formatToExportTo : this.exportOptions[0]
};
[...]
<Select value={this.state.formatToExportTo}
style={{width : "10em"}}
onChange={event=> {
this.setState({formatToExportTo : event.target.value})
}}>{
this.exportOptions.map(f=><MenuItem key={f} value={f}>{f}</MenuItem>)
}</Select>,
And my problem is that my Select component dosen't update its value after selecting another option.
So far I've tried :
setState({...this.state, formatToExport : event.target.value}) in the onChange= of the Select and in the Select tag : value = {this.state.formatToExport}
setState({...this.state, formatToExport : event.target.value}) in the onClick= of each options and in the Select tag : value = {this.state.formatToExport}. But that was only to see the update, because the event.target.value isn't right anyway
and the current version of my lines written above also onClick OR onChange (without tthe cloning of state which is supposed to be done by setState alone).
It's like in the official example so I truly don't see where this lack of update could come from. No matter what I try, the currently displayed value of the Select component doesn't change is display, even though the state was properly updated
Thank you for the time you took to read me !

After searching for 3 hours total :
normally value={this.state.formatToExportTo} should work ( I tried it alone without the rest of my app surrounding it)
But since I made some quircky things with my this and the order of update, I just had to replace :
value={this.state.formatToExportTo} by defaultValue={this.state.formatToExportTo}
That's all ! I hope it helps someone who'll come by this question

Related

Why List element only gets selected when clicked twice?

I am building a React application and using react-final-form library. I am rendering a select component, but on selecting an item it doesn't get selected. On selecting again, then only it gets selected. I'm not sure why select component state is not getting changed ? Could anyone please check and assist.
Here is the code sandbox link : https://codesandbox.io/s/broken-sunset-9ogwc8?file=/src/Components/Actors.jsx
Regards.
In your NativeSelectField.jsx, change the onChange handler as below:
<NativeSelect
...
...
onChange={(event) => {
input.onChange(event.target.value);
}}
...
...
/>
Working Demo

StencilJS: How to prevent "flickering" when loading component in a page

A group of volunteers has created a single/multi-select component using StencilJS: https://github.com/NothingAG/adg-components
Now we want to hand it over to the client so they can use it in their project. But we notice that loading the component seems to take some time after the page itself loaded, so some flickering appears (when the loaded component claims its horizontal space):
Is this normal behaviour of such a component? Or how can we allocate the needed space when the browser is rendering? We could try to simply use min-height or something with a fixed value, but this feels like a hack and may change over time.
Thanks a lot for help.
This is normal. A Stencil web component will go through its load lifecycle asynchronously after being loaded into DOM, and therefore it may not complete until after the DOM has completed loading and the page is rendered. If the component has to make a call to fetch data for example before it fully renders, that might take long enough for this "flicker" to be noticeable.
Strategies for dealing with this type of situation will depend on the component, but in your case it looks like one approach would be to render the labels and controls without selection items and maybe disabled so that the initial render can occur early, and trigger a component update via a State variable when fetched data becomes available which simply populates the selection controls, and possibly enables them.
So - and I'm making guesses about how your component works - rather than conditionally render the controls, conditionally populate the controls.
Crude example of rendering a select element empty until data is set on the component via a property (code not validated):
private _selectionItems = [];
#Prop() selectionItems: string = ''; // csv list of select options
#Watch('selectionItems')
setSelectionItems(selectionItems: string) {
selectionItems = selectionsItems || ''; // null check
this._selectionItems = selectionItems.split(',');
}
render() {
return (
<label for="my-select">Choose an item:</label>
<select id="my-select">
{this._selectionItems.map(
item: string => <option value={item}>{item}</option>
)}
</select>
);
}
Contrast with not rendering at all until data is set (showing render function only):
render() {
if (this._selectionItems.length > 0) {
return (
<label for="my-select">Choose an item:</label>
<select id="my-select">
{this._selectionItems.map(
item: string => <option value={item}>{item}</option>
)}
</select>
);
}
else {
return null;
}
}

Semantic UI React, Dropdown Selection

Please take a look at my code for Dropdown,
I'm using the semantic ui react dropdown on an EditProfile component. I have pasted a sample code here, https://codesandbox.io/s/m4288nx4z8, but I could not get it to work because I'm not very familiar with functional components in React, I've always used Class component. But you can check the full code for the whole component below in the github gist.
https://gist.github.com/mayordwells/b0cbb7b63af85269091f1f98296fd9bb
Please, I need help on inserting values from multiple select options of a Dropdown into the Database and also a way to display that back upon viewing the profile edit page again.
I'm using semantic-ui-react in react + rails app.
Also when I insert a value using a normal drop down without multiple select, the value gets persisted into the database.
<Dropdown
placeholder='Select Country'
fluid
search
selection
options={countryOptions}
name='country'
defaultValue={this.state.extraInfo.country}
onChange={(e) => this.handleExtraInfoChange('country', e)}
/>
This code handles change for the dropdown elements.
handleExtraInfoChange = (name, event) => {
let value;
if (event.target.value !== undefined) {
value = event.target.value;
} else {
value = event.target.textContent;
}
let newExtraInfo = Object.assign(this.state.extraInfo, { [name]: value })
this.setState({ extraInfo: newExtraInfo});
}
But when I visit the page again, I get a white blank in the input box. Here's a screen pic for that. When I comment out the defaultValue or value property(i have tried with defaultValue and value), the white blank disappears, but the value picked by a user is also not seen.
Please advice what is a possible solution to this misbehavior? And what is the best way to insert multiple values into the Database?
Thanks in advance for your time.
A functional component does not have state, it's used for composition; you want to store state, so you either have to create a Component class or you need an external state container like redux.

React components rendering incorrectly

I have a react project, a recipe box, which includes the ability to open a recipe and add/delete ingredients. Here is a fiddle. You can click the recipe name to open the recipe. There is an edit button which reveals the delete button and gives the option to change the name of the ingredients. When the 'delete ingredient' button is pressed, the last ingredient appears to always be deleted, regardless of which ingredient is selected, but when the 'done' button is clicked and the editable input boxes change back to text, the correct change is shown, the proper ingredient deleted and the last ingredient remains. Though this works functionally, it's obviously not very UI friendly, and I wondered why this was happening. Any help would be great.
jsFiddle
class Input extends React.Component {
render() {
const array = this.props.update;
let booleanButton = null;
if (this.props.ingr) {
////////////////////////////
// here is the button's JSX
booleanButton = <button onClick=
{this.props.handleDeleteIngredient.bind(this, array)}>delete
ingredient</button>;
///////////////////////////
}
return (<div><form><input type="text" defaultValue={this.props.text}
onChange={this.props.onChange.bind(this, array)} /></form>{booleanButton}
</div>)
}
}
And the handler:
handleDeleteIngredient(data, e ) {
var key = data[2];
var ingrs = this.state.ingrs;
ingrs.splice(key, 1);
this.setState({ingrs:ingrs});
}
Your description is quiet confusing, and according the your fiddle code I think your problem is caused by not setting a good key for your list Item.
from what it looks in this line, you don't have a key={ingrs[i]} props, try set it to id see it will work, but making ingrediant name as key is probably not a good idea, try to give an actual id.
ingrList.push(<Input key={ingrs[i]} handleDeleteIngredient={this.handleDeleteIngredient.bind(this)} id={id} update={[this.props.objectIndex, "ingrs", i]} onChange={this.onInputChangeIng.bind(this)} text={ingrs[i]} />);

React.JS, pass data between components

very new to react. you can say I have not yet started to think like React.
here is the problem:
<div>
<DropDown> </DropDown>
<Panel> </Panel>
</div>
In the dropdown, I select a value. Store it in state, as something as , currentLocation.
Then I go to Panel, hit a button, and I want to open a modal. When i open a modal, I need to pass the currentLocation to that model.
I can pass in arbitrary value to modal, but I cannot figure out a way to get the currently selected item from DropDown.
How do I get the value of the currently selected item to the Panel?
Am I even making sense?
When you call the setState in the dropdown that will force an update of the page.
Then if you call this.state in your component you should have the value you need there.
You should go over the basic tutorials to grasp the react basics.
But it goes like this:
getInitialState: function() {
return {
myVar: ''
//set your variables here
//getInitialState will get called before the component gets mounted
};
},
myCustomFunction: function(newVariable) {
this.setState({
myVar: newVariable
});
},
render: function() {
return (
<div>
<input
onChange={this.myCustomFunction}
/>
<MyCustomComponent myProp={this.state.myVar}/>
//everytime the state changes MyCustomComponent will have that new value as a prop
</div>
);
}
There is a lot of ambiguity in your question but I'll try for the simplest case.
You have a Panel component and a Dropdown component.
You want to the Panel to have access to a value that was set when the Dropdown was used.
Solution: When the Dropdown is actuated, it creates an Action that Stores the selected value.
When the modal button in the Panel is actuated, it creates an Action that requires the DropDownStore. Then it decides what to do based on that value.
The pattern I am loosely describing is known Facebook's Flux architecture which is basically just a more specific application architecture for React applications similar to pub/sub or an event bus.

Categories