"toggled" attribute not working (redux-form-material-ui) - javascript

I'm trying to use Toggle from redux-form-material-ui:
import { Toggle } from 'redux-form-material-ui'
It works ok updating the toggled value to the store on its onChange:
<Col xs='3'>
<h3 className="title-page">Parceiro</h3>
<Field name="possui-parceiro" component={Toggle} label="Possui parceiro?" />
</Col>
Problem is: I make a call to some API and I need to update the value of this toggled "programatically". Theoretically, I can use the toggled attribute as stated here, but this just doesn't work:
<Col xs='3'>
<h3 className="title-page">Parceiro</h3>
<Field name="possui-parceiro" component={Toggle} toggled={this.state.someBloodyState} label="Possui parceiro?" />
</Col>
Which leads me to believe that in this case redux-form is just on the way of the update / manipulation process, forcing me to somehow update the form on the store to toggle the value, and it looks messy to dispatch such action. Anyway, how do you proceed in such cases?

I would store the API result in the redux state, read it from your mapStateToProps and pass it to the component in the property initialValues setting enableReinitialize: true.
These 2 properties are the way of redux-form to change stuff programmatically "later on" after the form already rendered.
Otherwise , if you can fetch your data before even rendering the form, you can just use initialValues without enableReinitialize.
Another way is to use the change function provided by redux form
More info in the docs

Related

Vue 3 Realoading component if variable change

I am trying to realod component if selectedLeague has been changed
<label class="label">Select league</label>
<div class="selector">
<v-select
v-model="selectedLeague"
:dropdown-should-open="dropdownShouldOpen"
:options="leagues"
label="displayLeague"
placeholder="Select a league"
/>
</div>
<div v-if="selectedLeague">
<LeagueTopScorers :is="selectedLeague" :selectedLeague="selectedLeague.id.toString()" />
</div>
In LeagueTopScorers component I am fetching API to get top scorers from selected league.
I tried :watch, v-on:, created()
<LeagueTopScorers /> does re-render when selectedLeague changes 1, but it doesn't re-mount.
It only mounts when selectedLeague changes from a falsy value to a truthy one (because that's when the value of the v-if changes).
There are a few problems with your question:
you're asking about a technical aspect (let's call it X), which you think will solve a business requirement (let's call it Y). It's a classical XY problem. Why don't you describe the Y requirement? (e.g: what you want to achieve). What output change do you want to see on what input change?
the code you posted is not enough to create a runnable example. We don't know what v-select is, what <LeagueTopScorers /> is, or how does :is prop look like on <LeagueTopScorers />.
From the snippet you posted, I am guessing the following:
v-select is either vue-select or Vuetify select component
you expect :is to work on <LeagueTopScorers /> as it does on <component />. Hint: it doesn't, unless you coded it yourself, which I doubt
last, but not least, I guess you want some code you placed into an init lifecycle hook of <LeagueTopScorers /> (e.g: onMounted) to run when you replace an object stored in selectedLeague with another object.
If I'm correct, the simplest and cleanest way to achieve this behavior is to create a computed 2:
const leagueId = computed(() => selectedLeague?.id.toString() || '')
... and use it in v-if, :key and :selectedLeague:
<LeagueTopScorers
v-if="leagueId"
:selectedLeague="leagueId"
:key="leagueId" />
(without the <div v-if> wrapper).
The above will create a new instance of <LeagueTopScorers /> every time leagueId changes and will only render one when leagueId is not falsy. I believe that's what you were trying to accomplish, technically 3.
Notes:
1 - to verify, use onUpdated(() => console.log('updated...'))
2 - use selectedLeague.value?.id.toString() if selectedLeague is a ref
3 - at the same time, I am sure the actual business requirement can be met without creating a new instance of <LeagueTopScorers /> every time leagueId changes, but I can't help more without more details and/or context

Material UI Autocomplete component not showing values from react state

I am trying to get value from the state for materialUI's autocomplete component.
I am facing the following problem : -
Autocomplte working fine for selecting the value and with onChange function it saving it into the state too.
But when I refresh my page/ re-render it is not showing value on the textfeild(from saved state):
<Autocomplete
name={"TideLocation"}
disabled={p.disabled}
options={data_source}
getOptionLabel={option => option.text}
inputValue={this.state.tidelocation_searchtext}
onChange={_this.handleUpdateTideLocationField}
onNewRequest={_this.handleChangeTideLocation}
onBlur={_this.handleBlurTideLocationField}
onUpdateInput={_this.handleUpdateTideLocationField}
renderInput={(params) => (
<TextField className="autoCompleteTxt"{...params} label="Location" />
)}
/>
I tried with the debugger and found its getting value in this.state.tidelocation_searchtext
but failed to set it with params.
Thanks in advance !!
Ps: I tried with defaultValue and search text nothing worked for me
following is my ONchangeFunction
handleUpdateTideLocationField = (str, value) => {
debugger
this.setState({tidelocation_searchtext: value.text});
}
after selecting a value,following value saved in sate :
tidelocation_searchtext: "Auckland"
So I found the solution all by myself by doing research and several hit and try, following is the solution of my problem:
<Autocomplete
name={"TideLocation"}
disabled={p.disabled}
options={data_source.map(option=>option.text)}
defaultValue={this.state.tidelocation_searchtext}
onChange={_this.handleUpdateTideLocationField}
onNewRequest={_this.handleChangeTideLocation}
onBlur={_this.handleBlurTideLocationField}
onUpdateInput={_this.handleUpdateTideLocationField}
renderInput={(params) => (
<TextField className="autoCompleteTxt"{...params} label="Location" />
)}
/>
Basically I was doing the following things wrong :
1.There is no need of using input inputValue={this.state.tidelocation_searchtext}& getOptionLabel={option => option.text}
2.as my data is in object form I have to convert it into a string so default value can match this from the state value
options={data_source.map(option=>option.text)}
Thank you all for your valuable support and solution !!
Removing inputValue has worked for me, even when passing object as options.
Using: "#material-ui/core": "^4.12.3"
If data/state not saved externally f.e. in local storage then it will be lost on page refresh, always. It's normal - like RAM memory without power - it (page/app state) only exists in memory !!
It's like using using cookie to keep you logged in.
If you really need such functionality then use f.e. redux-persist
You are right, if object type options are passed, material-ui's AutoComplete component does not seem to reflect the value when mounted. (Perhaps a bug?)
I was able to get around this by passing the proper characters to inputValue.
#RebelCoder
Maybe you should have initialized tidelocation_searchtext.
For me it was coming from the dropdown z-index which was hidden by another css behaviour.
I added this in a css file :
/* Dropdown MUI Component Autocomplete*/
div[role="presentation"].MuiAutocomplete-popper {
z-index: 1000000;
}
And it appeared finally. A bit hacky, but I think it was caused by another library that had something of that kind.
Note that I added several css elements to the selector, because just using the class wasn't enough.

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
});
}

InitalValues don't change even though the state they are set to does

I have a Semantic-UI modal that contains a redux-form as it's content. When opening the modal, I pass the form to it's content prop. The form element has an initialValues prop set to a prop mapped to state.
<FormModal
handleSubmit={ this.sortSubmit }
size='small'
formName='sortForm'
header='Sort'
headerIcon='sort'
content={
<SortForm table={ this.props.table } initialValues={ { orderBy: this.props.search.orderBy, orderDirection: this.props.search.orderDirection } } />
}
trigger={
<Button icon floated='right' size="mini">
<Icon name='sort' />
</Button>
}
/>
I then change this.props.search.orderBy by changing the redux state. Everything in the app updates to reflect the change, except this redux-form's initialValues, which should change when the state changes. I open the modal again, and the fields are reset to the old initialValues instead of the newly set values.
Any ideas why this would happen?
On a possibly related note, re-rendering the modal JSX does not seem to close the modal. Since the modal's initial state is closed, I would have assumed a re-render of it would re-close it.
You need to pass enableReinitialize={true} to your form.
Because enableReinitialize defaults to false. In this case, initialValues is only applied at componentWillMount.
Here is the part of doc about enableReinitialize:
When set to true, the form will reinitialize every time the
initialValues prop changes. Defaults to false. If the
keepDirtyOnReinitialize option is also set, the form will retain the
value of dirty fields when reinitializing.
For more info, please read reduxForm

Which event to use for emitting change from inputs?

I have a React component that has many <TextInput> components, which are just simple wrappers around text <input> elements. Example:
<div>
<TextInput value={person.FirstName} ... />
<TextInput value={person.LastName} ... />
</div>
I also have some state represented by a person object. For example:
{
"FirstName": "Buster",
"LastName": "Posey"
}
Each <TextInput> component manages it's own internal state, which is the value of the text <input> at a given time.
When I click on a Save button, I want to make sure the person object has the most recent values from all of the <TextInput> components.
I can think of two ways to do this:
Events (onKeyDown, onChange, onBlur). An event inside the <TextInput> will create an action, it goes through the dispatcher, and the store updates the person object one field at a time.
Refs. I know this is an anti-pattern, but it really does seem so much simpler. I can iterate over refs when Save is clicked and pull out the state and fire an action.
What is the idiomatic way of doing this?
If it's just a simple wrapper around input, give it the same api as input, and don't have it manage internal state it doesn't need to.
render(){
var person = this.state.person;
return <div>
<TextInput value={person.FirstName} onChange={this.handleFirstNameChange} />
...
</div>
},
handleFirstNameChange(name){
this.setState({person: update(this.state.person, {
FirstName: {$set: name}
}});
}
update is React.addons.update, just as an example
And when save is clicked you send it out in an action. You can have a store for each piece of temporary data if you really need to, but it's almost always overkill if you don't persist it.

Categories

Resources