[英]How to make a react component with Async data re-usable in Redux flow?
RoleField
应该是一个愚蠢的组件,它从UserForm
组件获取数据。 UserForm
应该从商店获取数据并将其作为props传递给RoleField
。 这样, RoleField
将是可重用的,因为它们可以显示从父组件传递给它们的数据。
UDPATE
您还可以将UserForm
为包装容器,该容器可以接受自定义表单字段作为子项。 请参阅下面的示例代码
render() {
<UserForm>
<RoleField customData={ dataFromStore }/>
</UserForm>
}
@DeividasKaržinauskas的答案在你有几个嵌套组件时很有意义,我认为这是合理的方式,但是因为我希望我的组件完全独立于任何其他组件,但是可测试且不包含任何组件数据逻辑我只想出了稍微不同的方法。 当然DeividasKaržinauskas的答案有所帮助。
为了使我的组件完全独立,我只是制作了另一个容器,所有副作用都由动作/动作创建者处理,并且它仍然是可测试的,而数据是由它自己的独立缩减器计算的。 然后我使用redux将状态作为道具传递。
代码示例
import React from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
class RolesField extends React.Component {
componentWillMount() {
//if not fetched then fetch
this.props.fetchRoles();
}
roles() {
let {roles} = this.props;
if (roles.length > 0) {
const {input, label, placeholder, type, meta: {touched, error, warning}} = this.props;
let rolesUi = roles.map((role, index) => {
return (
<div className="checkbox" key={index}>
<label htmlFor={input.name}>
<input {...input} placeholder={placeholder} type={type}/>
{role.name} <a href="#">( Show Permissions )</a>
</label>
</div>
);
});
return rolesUi;
}
}
render() {
const {input, label, placeholder, type, meta: {touched, error, warning}} = this.props;
return (
<div className="form-group">
<label className="col-sm-2 control-label" htmlFor={input.name}>
Administrative Roles
</label>
<div className="col-sm-10">
{/*This section should be loaded from server,
the component should dispatch the event and role action should load the roles.*/}
{this.roles()}
</div>
</div>
);
}
}
//map state to props.
function mapStateToProps(state) {
return {
roles: state.roles.roles
}
}
function mapDispatchToProps(dispatch) {
let actionCreators = {
fetchRoles
};
return bindActionCreators(actionCreators, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(RolesField);
/*Action Types*/
const ROLE_FETCH_START = 'ROLE_FETCH_START';
const ROLE_FETCH_COMPLETE = 'ROLE_FETCH_COMPLETE';
/*End Action Types*/
/**
* Action Creator
* @returns {{type: string, payload: [*,*,*,*]}}
*/
function fetchRoles() {
const roles = [
{'id': 1, 'name': 'Super Admin'},
{'id': 2, 'name': 'Admin'},
{'id': 3, 'name': 'Manager'},
{'id': 4, 'name': 'Technical Lead'}
];
/*Action*/
return {
type: ROLE_FETCH_COMPLETE,
payload: roles
};
}
/**
* Roles Reducer
* @param state
* @param action
* @returns {*}
*/
export function rolesReducer(state = {roles: [], fetched: false}, action) {
switch (action.type) {
case ROLE_FETCH_COMPLETE :
return {
...state,
fetched: true,
roles: action.payload
};
break;
}
return state;
}
并以还原形式重新使用组件我做了
import React from 'react';
import {Field, reduxForm} from 'redux-form';
import {renderInputField, renderDropdownList} from '../../page/components/field.jsx';
import RolesField from '../../page/containers/fields/roles.jsx';
import Box from '../../page/components/box.jsx';
import ActionButtons from '../../page/components/action-buttons';
class UserForm extends React.Component {
actionButtons() {
return [
{
'type' : 'submit',
'label' : 'Save',
'className' : 'btn-primary'
},
{
'type' : 'button',
'label' : 'Cancel',
'className' : 'btn-success',
'onClick' : this.props.reset
},
{
'type' : 'button',
'label' : 'Delete',
'className' : 'btn-danger'
}
]
}
render() {
const { handleSubmit } = this.props;
return (
<form className="form-horizontal" role="form" onSubmit={handleSubmit}>
<Box title="Add New User">
<ActionButtons buttons = {this.actionButtons()} />
<Field
name="roles[]"
component={RolesField}
label="Technical Lead"
type="checkbox"
className="form-control" />
</Box>
</form>
);
}
}
UserForm = reduxForm({
form: 'userForm',
validate
})(UserForm);
export default UserForm;
这是修改后的图表。 我不确定这是最佳做法还是有任何与之相关的缺点,但它只适用于我的用例。
州图:
对图表的道歉并不那么清楚。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.