使用 React、Redux 更新项目列表。和 Redux 形式
Updating Item Listing using React, Redux. and Redux Form
添加马匹操作完成后如何更新马匹列表?
我认为 CreateHorse 中的 reloadHorseList 是 运行 在 createHorse 操作完全完成之前,所以有时我会在列表中看到新马,有时却看不到。完全重新加载始终显示更新。
马匹组成部分
...
import { getHorses } from '../../actions';
import ListHorses from './ListHorses';
import CreateHorse from './forms/createHorseForm';
class Horses extends React.Component {
constructor(props) {
super(props);
this.state = {
...
};
this.reloadHorseList = this.reloadHorseList.bind(this);
}
componentDidMount() {
this.reloadHorseList();
}
reloadHorseList() {
this.props.getHorses(this.props.current_user.selected_stable);
}
render() {
return (
<div className="content page-content-wrapper1">
<CreateHorse
current_user={this.props.current_user}
reloadHorseList={this.reloadHorseList}
/>
<ListHorses
current_user={this.props.current_user}
horses={this.props.horses}
/>
</div>
);
}
}
function mapStateToProps(state) {
return {
horses: state.horses
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
getHorses: getHorses
},
dispatch
);
}
export default connect(mapStateToProps, mapDispatchToProps)(Horses);
创建马形态
...
import { Field, reduxForm, getFormValues } from 'redux-form';
import {
createHorse,
getHorseSelect,
updateHorseCount
} from '../../../actions';
import { connect } from 'react-redux';
const renderField = (...
);
class CreateHorse extends Component {
constructor(props) {
super(props);
this.state = {
...
};
this.setMessage = this.setMessage.bind(this);
}
onSubmit(props) {
//let p = this.props.reloadHorseList;
try {
this.props.createHorse(props, this.setMessage);
//running before I have finished creating my horse
this.props.reloadHorseList();
} catch (err) {
...
}
}
render() {
const { handleSubmit } = this.props;
return (
<div>
...
{this.state.displayHorseCreateForm && (
<div>
<h4 className="header-content">Add Horse</h4>
<p> * required field</p>
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
// fields here
<button type="submit" className="btn btn-primary">
Submit
</button>
</form>
</div>
)}
</div>
);
}
}
function validate(values) {
...
}
function mapStateToProps(state) {
---
}
export default connect(mapStateToProps, {
createHorse,
getHorseSelect,
updateHorseCount
})(
reduxForm({
form: 'HorseCreatetForm',
initialValues: {
...
},
validate
})(CreateHorse)
);
//create horse action
export const createHorse = (props, setMessage) => async dispatch => {
try {
const request = await axios.post(`/api/horse/create`, props);
return {
type: CREATED_HORSE,
payload: request.data
};
} catch (err) {
...
}
};
马匹名单
...
import { deleteHorse } from '../../actions';
class HorsesList extends React.Component {
render() {
let horses = this.props.horses;
let horseCount = this.props.horse_count;
return (
<div className="content">
horse count: {horseCount}
<ul className="list-inline box-body">
{horseCount > 0 &&
horses.map((horse, key) => (
<li key={key}>
...//listing here
</li>
))}
</ul>
</div>
);
}
}
function mapStateToProps(state) {
return {
horse_count: state.horse_count
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
...
},
dispatch
);
}
export default connect(mapStateToProps, mapDispatchToProps)(HorsesList);
此时您应该发布真实代码。要触发组件重新渲染,您需要更改它的状态。我建议将你的道具从 redux 设置为本地状态并从中呈现你的列表。您还需要使用 componentWillRecieveProps();
componentDidMount() {
this.reloadHorseList();
this.setState=({list: this.props.horseList});
}
componentWillRecieveProps(nextProps){
this.setState=({list: nextProps.horseList})
}
您假设组件首先完成加载是正确的。所以你需要利用 componentWillRecieveProps lifecycle hook 。
或者,如果您将 mapStateToProps() 与 redux 一起使用,则当 mapStateToProps() 中的任何内容发生变化时,您的组件应该重新渲染。
对我有用的解决方案是向 CreateHorse 组件发送回调以发送到 createHorse 操作,该操作运行 Horse 组件操作以获取 Horses。
class Horses extends React.Component {
constructor(props) {
super(props);
this.state = {
horses: this.props.horses,
};
this.reloadHorses = this.reloadHorses.bind(this);
}
componentDidMount(prevProps) {
this.props.getHorses(this.props.current_user.selected_stable);
}
reloadHorses = () => {
this.props.getHorses(this.props.current_user.selected_stable);
};
...
<CreateHorse
current_user={this.props.current_user}
reloadHorses={this.reloadHorses}
/>
<ListHorses
horses={this.props.horses}
/>
...
function mapStateToProps(state) {
return {
horses: state.horses
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
getHorses: getHorses
},
dispatch
);
}
export default connect(mapStateToProps, mapDispatchToProps)(Horses);
然后在CreateHorse组件中
onSubmit(props) {
this.props.createHorse(props, this.setMessage, this.props.reloadHorses);
}
}
然后在createHorse动作中
export const createHorse = (
props,
setMessage,
reloadHorses
) => async dispatch => {
try {
const request = await axios.post(`/api/horse/create`, props);
reloadHorses();
return {
type: CREATED_HORSE,
payload: request.data
};
} catch (err) {
...
}
};
添加马匹操作完成后如何更新马匹列表?
我认为 CreateHorse 中的 reloadHorseList 是 运行 在 createHorse 操作完全完成之前,所以有时我会在列表中看到新马,有时却看不到。完全重新加载始终显示更新。
马匹组成部分
...
import { getHorses } from '../../actions';
import ListHorses from './ListHorses';
import CreateHorse from './forms/createHorseForm';
class Horses extends React.Component {
constructor(props) {
super(props);
this.state = {
...
};
this.reloadHorseList = this.reloadHorseList.bind(this);
}
componentDidMount() {
this.reloadHorseList();
}
reloadHorseList() {
this.props.getHorses(this.props.current_user.selected_stable);
}
render() {
return (
<div className="content page-content-wrapper1">
<CreateHorse
current_user={this.props.current_user}
reloadHorseList={this.reloadHorseList}
/>
<ListHorses
current_user={this.props.current_user}
horses={this.props.horses}
/>
</div>
);
}
}
function mapStateToProps(state) {
return {
horses: state.horses
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
getHorses: getHorses
},
dispatch
);
}
export default connect(mapStateToProps, mapDispatchToProps)(Horses);
创建马形态
...
import { Field, reduxForm, getFormValues } from 'redux-form';
import {
createHorse,
getHorseSelect,
updateHorseCount
} from '../../../actions';
import { connect } from 'react-redux';
const renderField = (...
);
class CreateHorse extends Component {
constructor(props) {
super(props);
this.state = {
...
};
this.setMessage = this.setMessage.bind(this);
}
onSubmit(props) {
//let p = this.props.reloadHorseList;
try {
this.props.createHorse(props, this.setMessage);
//running before I have finished creating my horse
this.props.reloadHorseList();
} catch (err) {
...
}
}
render() {
const { handleSubmit } = this.props;
return (
<div>
...
{this.state.displayHorseCreateForm && (
<div>
<h4 className="header-content">Add Horse</h4>
<p> * required field</p>
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
// fields here
<button type="submit" className="btn btn-primary">
Submit
</button>
</form>
</div>
)}
</div>
);
}
}
function validate(values) {
...
}
function mapStateToProps(state) {
---
}
export default connect(mapStateToProps, {
createHorse,
getHorseSelect,
updateHorseCount
})(
reduxForm({
form: 'HorseCreatetForm',
initialValues: {
...
},
validate
})(CreateHorse)
);
//create horse action
export const createHorse = (props, setMessage) => async dispatch => {
try {
const request = await axios.post(`/api/horse/create`, props);
return {
type: CREATED_HORSE,
payload: request.data
};
} catch (err) {
...
}
};
马匹名单
...
import { deleteHorse } from '../../actions';
class HorsesList extends React.Component {
render() {
let horses = this.props.horses;
let horseCount = this.props.horse_count;
return (
<div className="content">
horse count: {horseCount}
<ul className="list-inline box-body">
{horseCount > 0 &&
horses.map((horse, key) => (
<li key={key}>
...//listing here
</li>
))}
</ul>
</div>
);
}
}
function mapStateToProps(state) {
return {
horse_count: state.horse_count
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
...
},
dispatch
);
}
export default connect(mapStateToProps, mapDispatchToProps)(HorsesList);
此时您应该发布真实代码。要触发组件重新渲染,您需要更改它的状态。我建议将你的道具从 redux 设置为本地状态并从中呈现你的列表。您还需要使用 componentWillRecieveProps();
componentDidMount() {
this.reloadHorseList();
this.setState=({list: this.props.horseList});
}
componentWillRecieveProps(nextProps){
this.setState=({list: nextProps.horseList})
}
您假设组件首先完成加载是正确的。所以你需要利用 componentWillRecieveProps lifecycle hook 。
或者,如果您将 mapStateToProps() 与 redux 一起使用,则当 mapStateToProps() 中的任何内容发生变化时,您的组件应该重新渲染。
对我有用的解决方案是向 CreateHorse 组件发送回调以发送到 createHorse 操作,该操作运行 Horse 组件操作以获取 Horses。
class Horses extends React.Component {
constructor(props) {
super(props);
this.state = {
horses: this.props.horses,
};
this.reloadHorses = this.reloadHorses.bind(this);
}
componentDidMount(prevProps) {
this.props.getHorses(this.props.current_user.selected_stable);
}
reloadHorses = () => {
this.props.getHorses(this.props.current_user.selected_stable);
};
...
<CreateHorse
current_user={this.props.current_user}
reloadHorses={this.reloadHorses}
/>
<ListHorses
horses={this.props.horses}
/>
...
function mapStateToProps(state) {
return {
horses: state.horses
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
getHorses: getHorses
},
dispatch
);
}
export default connect(mapStateToProps, mapDispatchToProps)(Horses);
然后在CreateHorse组件中
onSubmit(props) {
this.props.createHorse(props, this.setMessage, this.props.reloadHorses);
}
}
然后在createHorse动作中
export const createHorse = (
props,
setMessage,
reloadHorses
) => async dispatch => {
try {
const request = await axios.post(`/api/horse/create`, props);
reloadHorses();
return {
type: CREATED_HORSE,
payload: request.data
};
} catch (err) {
...
}
};