I am saving the form data in react to redux store and every input works fine except the checkbox. The problem is that checkbox never shows tick mark but redux-logger shows that the state of the checkbox has been changed in the state. Below is my checkbox
<Control.checkbox model="agree" name="agree"
className="form-check-input"
changeAction={this.changeAction} defaultChecked={this.props.fields.agree}
updateOn="toggle"
/> {' '}
<strong>May we contact you?</strong>
this.props.fields.agree gives the current status of the checkbox tken from redux store.
Below is the reducer:
const InitialFeedback={
firstname: 'Vipul',
lastname: 'Tyagi',
telnum: '12345',
email: 'vipultyagi629#gmail.com',
agree: true,
contactType: 'Email',
message: 'Hello'
};
export const formsData=(state=InitialFeedback,action)=>{
switch(action.type){
case 'CHANGE_FIELD':
return {...state, [action.payload.name]: action.payload.value};
default:
return state
}
}
Below is the changeAction method:
changeAction(model, value){
console.log(typeof(value));
this.props.dispatch({type:'CHANGE_FIELD',payload:{name: model, value: value}});
}
The checkbox indeed respond to tick but doesn't shows tick mark. What mistake I am doing?
Please help me to find the problem!!
EDIT
I have just checked that whatever the initial state of checkbox is, it always remains same. I mean if initially in store I set agree to true then the checkbox starts showing tick mark, but on clicking on the checkbox, the tick mark doesn't goes off. Similar is the for the case when initial state is false.
Related
On a button, I have a onClick handler
const handleSelectOpen = (noteId) => {
let newState = {notes: state.notes, noteDetailScreen: true, activeNote: noteId, newNoteScreen: false, newNoteText: "", newNoteRelated: []};
setState(newState);
};
Which does two important things, it sets noteDetailScreen in the state to true, causing the MUI Dialog to appear. It also sets activeNote to noteId, which is the content that should be displayed in the dialog.
That content is then displayed with {state.notes[state.activeNote].content} inside the dialog. The issue being most of the time, its displaying the wrong content! noteId is always correct, but the state is not always correct. How can I fix this>
when updating state based on the previous state, you should pass an updater function to setState. It takes the pending state and calculates the next state from it.
setState(prev => ({notes: prev.notes, noteDetailScreen: true, activeNote: noteId, newNoteScreen: false, newNoteText: "", newNoteRelated: []}))
I've three buttons on the page, and when clicking on any button i want to get that selected value from the store filtered by id(done in reducer). I'm trying to use redux with mapStateToProps and mapDispatchToProps pattern, but looks like when i try to access the current selected value from the store after clicking on any button, it doesn't reflect the correct value in the console. Is this not how "this.props.anyPropValue" be used? Can you help clarify what's wrong in my example?
First time it prints default value when clicking any button, clicking again prints the previously clicked button value not the current one.
Here is a sandbox link to the simple app i created for the above
sandbox link of the code
Most of the code that you have wrote is correct, If you are expecting to see the updated output right after calling the action, it won't work
onGetCountryById(id) {
this.props.fetchCountryById(id);
console.log(this.props.country); // This will gives you the current country (We just update the state, but still that value didn't update the component)
}
try to print the value of the country in the html as below and you will see it's getting updated
{this.props.country === null ? "default" : this.props.country.name}
in the reducer you might need to do this change
case CountryActions.FETCH_COUNTRY_BY_ID:
return {
...state,
country: state.countries.find((item) => item.id === action.id) // use find instead of filter
};
and set the initial value of the country set to null
const initCountriesState = {
country: null,
countries: [
....
]
};
here is the updated sandbox
I have an antd form which has a select component as form item. Something like this:
<Form.Item label='Client Name'>
{
getFieldDecorator('clientId', {
rules: [{
required: true,
message: 'Please select client!',
}],
initialValue: this.state.clientId
})(
<Select
showSearch
loading={this.props.isClientLoading}
optionFilterProp='title'
style={formItemStyle}
placeholder='Select Client'
onChange={this.handleClientChange}
>
{this.props.clientOptions}
</Select>
)
}
I am maintaining a state for clientId. Whenever user selects an option from select dropdown, I update the state value in method handleClientChange. But, in one condition, I don't want to update the state value and in that case dropdown selection should also not change. But the thing is select calls handleClientChange method and then updates the dropdown field. My handleClientChange code looks something like this:
handleClientChange = async (selectedClientId: any) => {
if (this.state.isSomethingChanged) {
debugger;
/* setTimeout(() => {
this.props.form.setFieldsValue({ clientId: this.state.clientId});
}, 100); */
this.props.form.setFieldsValue({ clientId: this.state.clientId});
As you can see, I tried to update props form value but it updates for a fraction of second and then select internally fires the new value and changes it.
As you can also see, I tried a work around of setting a timeout and it works but that is a very unpleasant UX. Can someone help me in restoring the old value of dropdown?
P.S. : I tried setting value prop of select component but that doesn't work when it is wrapped in getFieldDecorator. Antd takes care of making it a controlled component.
If you do not want a particular option to be selected:
Do not create an option for it
Make is disabled so that it cannot be selected
As title says, I set up a checkbox which has the issue that I need to click on it twice to change it's state
The first time I click it behaves as expected, but every attempt after that requires double clicking.
state = {
notification: true,
};
handleInputChange= (event) => {
//I use event.target to operate since I'm trying to set up multiple checkboxes
this.setState({ [event.target.id]: !event.target.checked });
};
<AppSwitch
checked={this.state.notification}
onChange={this.handleInputChange}
className={"mx-1 switch-color"}
color={"success"}
variant={"pill"}
id="notification"
name="notification"
/>
You don't need to ! when you're setting state here. It should be this.setState({ [event.target.id]: event.target.checked });, since event.target.checked returns the checked state of the checkbox. So, if you click the checkbox and it transitions to checked, then it will be true. Then, if you click the checkbox and it transitions to unchecked then it will be false.
I'm currently wondering how to go back to the form's initial state after cancel.
Here is the scenario:
I have a user information form that I need to update.
In the form, I can already see my data.
I changed a value in one of the fields.
After changing the value, I realized I do not want to update it yet so I click cancel.
When I click on Cancel, it should go back to the original data.
My current situation is that when I click on cancel, I am using resetFields(); function which clears all the input fields.
const cancel = () => {
form.resetFields()
}
Are there any suggestions?
You need to save the initial state, on cancel not .resetFields() but use .setFields({}) to reset.
Read docs about form instance
Here example:
form.setFields({ ...state })
Initial state save in this format:
{
firstInput: {
value: 'value', errors: []
},
secondInput: {
value: 'value', errors: []
}
}