Dynamic defaultValue on Combobox React Widgets - javascript

I'm fairly new to javascript and I'm currently making a web client that display some data a database. Pretty standard stuff I guess. I use react.js and I installed react-widgets to get some nice widgets. The comboxbox I use is getting it's data from a mongo database depending on the collection chosen from another comboxbox. So by changing the collection, the data inside is updated to reflect the change. This works well, but I can't seem to be able to set the default value. Here the code to render the comboxbox:
<Combobox onChange= {this.handleOnChange} data = {this.state.myValues} defaultValue= {this.state.myValues[0]}/>
I have had this issue with a couple of widgets that does not seem to be able to get updated dynamically. They work if all the data is there the first time I'm rendering (static data for example), but they don't if the data is empty at first and gets populated afterward. *I did make sure I call setState to call the render function.
Did I miss something? Is it a javascript issue that I don't understand?
Thanks!

Try wrapping the Combobox with a condition.
Something like this
{ this.state.myValues[0] &&
YOUR_TAG_COMBO
<Combobox onChange= {this.handleOnChange} data = {this.state.myValues} defaultValue= {this.state.myValues[0]}/>
}

I think you might be better off using the value prop, instead of defaultValue, it will give you more control over the component, and it will repopulate the form element when the state has changed.

Related

Update the cache and trigger a re-render in Apollo

I'm trying to update the cache of a certain item but changes aren't being reflected on to the ui , I have an item which is being fetched by a query that has a lot of variables and I have no access to them on the component that I'm updating that Item on and that Item is also part of a paginated list , so my code was
update = (cache)=>{
cache.data.data['ItemType_'+itemId].title = "New title"
}
as far as I know this code should update the cache of that item but it doesn't show it in the ui , is there a way to update a single item in the cache and have the result rendered ?
Directly updating the cache doesn't cause a re-render afaik. I recommend running a query with fetchPolicy: "cache-only" after you update the cache. That will update the component's data and cause a re-render without hitting the network.
Try and also make sure you are returning the correct data from the mutation.
Return the correct fields from the mutation. The required field can be id. If it is not returned from the mutation, then there will be no refresh or re-render.

PrimeVue Datable not updating

Im pretty new to Vue and JS, so Im having a hard time understanding how it all works. Im coming from Swift and maybe that is the problem.
Im trying to get a Primevue datable to update its values when changing out the values in a ref connected to it. But nothing happens on screen, however the console.log file shows the new data.
//Vue composition api setup()
const { flights } = getCollection("Jobs", shift.value.email, fullDay + platform.value.name)// Firebase Listener
//This function is triggered by some select buttons which changes the shift.value and platform.value so to listen for data in a different collection
const loadFlights = () => {
let {flights: fl} = getCollection("Jobs", shift.value.email, fullDay + platform.value.name)
flights.value = fl.value
console.log('flights ref:', fl, ) // shows new the data, but the datable does not.
}
If Im not clicking to change to a different collection the datable updates the current collection fine. Is there some sort of "tableview.reload()" fuctionality here Im missing?
Solved it. I used watch from vue instead which triggers everytime the select value changes.
I then stored the response in a reactive parameter instead of a ref. And now it works like it should. Cant tell you why.
https://youtu.be/Qypxpm-llnQ
Program with Erik most likely can.

Re-Render only a particular child

I am building a dynamic form and as of now, my component hierarchy is as follows:-
App
Caseform
DynamicFormBuilder
Context.Provider
Patients
Patient key = "patient_1"
ComponentCreator key = "patient_1_1"
Textbox
ComponentCreator key = "patient_1_2"
Textbox
ComponentCreator key = "patient_1_3"
Textbox
Patient key = "patient_2"
ComponentCreator key = "patient_2_1"
Textbox
ComponentCreator key = "patient_2_2"
Textbox
ComponentCreator key = "patient_2_3"
Textbox
As of now, I have hardcoded JSON data in caseform but eventually, it will come from the fetch call. As soon as DynamicFormBuilder receives the caseform metadata, it creates states out of it.
I am maintaining state at caseform level even for its child. I thought of doing it that way because the requirement was to support patch save(send only changed data to the backend on save button press). If anybody knows of a better way of doing this, please let me know.
I am passing in a function using context API to child components so that they can update the state in DynamicFormBuiler.
The issue I am facing is that let's say even if the user edits one textbox, the whole Dynamic form gets rendered.
I have gone through a lot of answers on StackOverflow that advise on using the shouldComponentUpdate lifecycle method, but I am not able to figure out how I will use it here.
I am adding a link to the sandbox and in the console, you can see that if a user edits a field all the things are rendered again.
CodeSandbox Link
Expected Behavior:- What I am looking for is for example:- if user-edited only one textbox say in patient 1 then only that textbox gets re-rendered again
This is my first time using react. I apologize in advance if someone feels I have not done enough research, I have read through a lot of questions but still facing some challenges, any help will be really appreciated.
If you wrap each component in the React.memo() HOC, this should prevent excessive rerenders.
https://reactjs.org/docs/react-api.html#reactmemo
-Edit-
Yes it works with class components too.
e.g.
const MyComponent = React.memo(class extends React.Component {
render () {
return <h1>TEST</h1>
}
});

React object.map not updating due to the key

The basic problem I'm having is that I'm updating my data using an AJAX request and then setting the state of data, but in the view, the data never update even though my state is updated. I've figured out that it's because the key is the same (which it should be because I'm just using the ID mongoose provides).
If I do things like set the state to nothing and then set then set the new data then it updates. Or if I set the key to a randomly generated key it also works, but both of these don't feel right. I want to know what the correct way to re-render an updated object when using the map function.
It looks something like this:
Object.keys(this.state.data).map((i) => (
<MyComponent key={ this.state.data[i]._id }
))
And then I have a basic AJAX request that does this.setState({ data: response.data }).
How do I make react update the data in the view for the updated item properly?
Can you add the index as a prefix to the _id?
key={ `${i}_${this.state.data[i]._id}`}
I am not really sure it is related to the key, if you console.log(this.state.data) just before your code it gets updated when it should? it seems to me that the props are not getting passed to the component.
I mean I often use the index of map in the key in the lists I never had any problem with that.

Building an autocomplete textbox with ReactJS

My idea is to mantain the list of filtered users (suggestions) as state on the component, when the input changes, the state is updated.
How can I display the filtered list below the text box?
One option is 'datalist' tag (HTML5), but the list is already filtered, and part of the functionality of this tag is filtering.
I can't use any library or framework.
English is not my native language, sorry if you find some mistake.
Thanks.
Try a component from a design library, like the Material-UI autocomplete component http://www.material-ui.com/#/components/auto-complete
The dataSource attribute represents the array of autocomplete options.
How I did it was to pass in the dataList array as a prop and filterByField prop so that you can change what to filter, then add an event listener to the input (onChange) that passes the value to a function that filters the dataList.
onChangeInput(e) {
const { dataList, filterByField } = this.props;
const filteredDataList = dataList.filter(items => items[filterByField].toLowerCase().startsWith(e.target.value.toLowerCase()) );
// update internal component state to trigger render of dropdown list
this.setState({filteredList: filteredDataList});
}
I also added a check for no matches found so I can show a message:
if (filteredDataList.length === 0) {
this.setState({noMatchFound: true});
}
Then in my render() I simply check if filteredList isn't null and show an unordered list that I use css to display below the input.
{this.state.filteredList !== null
<ul className="autocomplete-list">
{this.filteredListMarkup()}
</ul>
}
filteredListMarkup() then uses map to return an <li> for each item with the necessary event handlers to update the selected item into the input and close the autocomplete-list by this.setState({filteredList: null});
You might also find this one useful:
https://github.com/reactjs/react-autocomplete
Even if you could use dependencies, I tried a bunch of the top current ones and personally wasn't happy with any of them (added dependencies like jQuery, not lightweight to use/understand/customize, css challenges, etc).
In then end, I found this lightweight vanilla React typeahead tutorial (no, I didn't write the tutorial). It's quick, simple, and three's no added dependency tree weight (eg: jQuery) or dependency maintenance. This solution also easily adjusted to the newer React patterns & the libraries I was using, and I'm guessing the same would be true of the patterns/libraries you may be using. Maybe this will help you or someone else like it did me.

Categories