I am creating a control for selecting a foreign key, named FKSelect.
It is directly connected to redux.
I need it to be part of the app's forms.
I use the "custom component" approach with RRF to set it up.
I use the model actions: actions.change(), actions.blur() in the component to update the appropriate model. That's working fine, the form and model state is updated, onSubmit the data is correct.
What I cannot get to work is setting the initial value of the component.
How should I do that? The component is connected to redux, so I guess I can use the value directly as it is in stored in the state. I do not use a wrapper component
As I said, it's not mentioned in the documentation, if you need help updating it, I am willing to give a hand.
Code:
<AutoComplete
openOnFocus={true}
filter={AutoComplete.noFilter}
searchText={valueLabel} // how to set initialValue?!
dataSource={renderedRecords}
onUpdateInput={dispatch(this.action.listRecords())}
// onChange
onNewRequest={(X, idx) => dispatch(actions.change(model, records[idx].id)) }
// onBlur
onBlur={() => dispatch(actions.blur(model))}
{...rest}
/>
The initial value is done the exact same way you would set up an initial value in a Redux reducer - by providing it to your initial state:
const initialState = { foo: 'bar' };
/*...*/ modelReducer('myModel', initialState)
And then it would be passed to the value={...} prop of your component. Is this not working, or does this not fit your use case?
initialState does not fit my use case, AFAIK.
I want to load a record from the server, and use that record as intitialState for the form. Subsequently actions.reset() would reset the values to the initially loaded from the server.
Specifying the values during redux store configuration does not allow that, again AFAIK.
Maybe if there is a method to set the initialValues, say ... actions.setInitialValue() ? But there isn't such method currently ...
Also, even if initialState was ok, then the second question is how I do connect that to the custom component? Using redux' connect() ?
@connect(state => ({modelValue: state['ReactReduxFormModel.myCustomField']})
Or, alternatively, how you would pass down the value from the form containing component to the custom field component)
Or, alternatively, how you would pass down the value from the form containing component to the custom field component)
Just like you would in normal Redux. Perhaps I don't fully understand your question. If you have a store that looks like this:
{
user: modelReducer('user', initialUserState)
}
and you actions.change('user.foo', 'bar'), you can reference that as expected in your connected component:
const { user } = this.props;
return (
<div>{ user.foo }</div>
);
So, are you asking how to _set_ a value to be the initial state that is retrieved asynchronously? That's more of a Redux question, not a RRF question. I suggest having a custom reducer:
function myCustomReducer(state = {}, action) {
switch (action.type) {
case 'SET_INITIAL_STATE':
return {
...state,
user: action.user,
initialUser: action.user
};
case 'RESET_USER_STATE':
return {
...state,
user: state.initialUser,
};
default:
return state;
}
}
and then you can decorate your existing reducer using modeled(reducer, model).
So, I encourage you, think about how you would solve this problem in plain Redux and then you can easily fit it in to RRF.
I think. the issue is this:
You have your data fetched, how do you populate the form (to set initialState to this data). For example, you have a page Article, which has a Form component in it. You fetch data in Article and want to populate the form with this data. Like this:
<Article>
<Form initialValues={fetchedData} />
</Article>
// or
Article {
componentDidMount() {
fetchData()
.then(data => {
dispatch(actions.setFormInitialValues('articleForm', data))
})
}
}
You can populate your form with actions.load():
dispatch(actions.load('article', data));
The articleForm (presumedly from a formReducer contains all of the _form_ information, such as if it's focused, valid, touched, submitted, etc. It doesn't carry any initialValue property (though it probably will in v1.0).
Are you wanting to have the capability to reset the _model_ to the initial value that you specify in the future? Again, that calls for a custom reducer since RRF's modelReducer() returns a state that is _just_ your model value, without any meta information.
So, unless you need to explicitly set the initial state for purposes of resetting the form at some point in time, actions.load() will allow you to do what you need to do.
@davidkpiano yes, the load method will do the job. I think, the question is about reset - how do you reset after you loaded the data (as this data is supposed to be initial state for a form).
I think, in this case, we can store fetched data somewhere and on reset - load it again into the form?
I think, in this case, we can store fetched data somewhere and on reset - load it again into the form?
Yep, I think this is the best idea, without making things too complicated.
You can do this in your model, by having an ad-hoc initialState property and then manually dispatching actions.change('myModel', myModel.initialState) when you want to "reset" it.
The reason there can't be a mechanism for setting the initial value at any time past store initialization is that if your store looks like this:
{ foo: 'bar' }
there's no way of knowing what the initial value of that was in a pure functional way without adding a meta property such as:
{ foo: 'bar', initialState: { foo: 'first' } }
@davidkpiano yes, currently this is the best option. Maybe after 1.0, initialState value will be added to the store so this case will be more simple to solve.
Hope this answers the topic starter's question.
Thank you very much for your answers.
I have missed the "decorating reducers" part in the documentation.
Having "user" and "initialUser" in redux state, and then decorating my current CRUD reducers will be the best option for now. And on form reset I will use actions.change('user', initialUser)
Most helpful comment
You can populate your form with
actions.load():The
articleForm(presumedly from aformReducercontains all of the _form_ information, such as if it's focused, valid, touched, submitted, etc. It doesn't carry anyinitialValueproperty (though it probably will in v1.0).Are you wanting to have the capability to reset the _model_ to the initial value that you specify in the future? Again, that calls for a custom reducer since RRF's
modelReducer()returns a state that is _just_ your model value, without any meta information.So, unless you need to explicitly set the initial state for purposes of resetting the form at some point in time,
actions.load()will allow you to do what you need to do.