在 React 生命周期中,componentDidMount()
只触发一次。
确保呼叫是从componentDidMount
and not发出的componentWillReceiveProps
。
如果调用真正来自componentDidMount
,则意味着您的组件每次都重新创建。可以通过console.log
在constructor
组件中添加一个来检查它。
在任何情况下,您都应该更喜欢使用redux的isFetching
and来处理数据获取/重新获取。didInvalidate
您可以在另一个问题中看到我对其工作原理的详细回答:React-Redux state in the component is different from the state in the store
如果我专注于您的用例,您可以在下面看到isFetching
anddidInvalidate
概念的应用。
1. 组件
看看 action 和 reducer,但 redux 的诀窍是使用isFetching
anddidInvalidate
道具。
当您想要获取数据时,唯一的两个问题是:
- 我的数据还有效吗?
- 我目前正在获取数据吗?
您可以在下面看到,无论何时选择一个程序,都会使获取的数据无效,以便使用新的 programId 作为过滤器再次获取。
注意:您当然应该使用connect
ofredux
将动作和减速器传递给您的组件!
MainView.js
class MainView extends React.Component {
return (
<div>
<ProgramDropdown />
<ContactDropdown />
</div>
);
}
ProgramDropdown.js
class ProgramDropdown extends React.Component {
componentDidMount() {
if (this.props.programs.didInvalidate && !this.props.programs.isFetching) {
this.props.actions.readPrograms();
}
}
render() {
const {
isFetching,
didInvalidate,
data,
} = this.props;
if (isFetching || (didInvalidate && !isFetching)) {
return <select />
}
return (
<select>
{data.map(entry => (
<option onClick={() => this.props.actions.setProgram(entry.id)}>
{entry.value}
</option>
))}
</select>
);
}
}
ContactDropdown.js
class ContactDropdown extends React.Component {
componentDidMount() {
if (this.props.programs.selectedProgram &&
this.props.contacts.didInvalidate && !this.props.contacts.isFetching) {
this.props.actions.readContacts(this.props.programs.selectedProgram);
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.programs.selectedProgram &&
nextProps.contacts.didInvalidate && !nextProps.contacts.isFetching) {
nextProps.actions.readContacts(nextProps.programs.selectedProgram);
}
}
render() {
const {
isFetching,
didInvalidate,
data,
} = this.props;
if (isFetching || (didInvalidate && !isFetching)) {
return <select />
}
return (
<select>
{data.map(entry => (
<option onClick={() => this.props.actions.setContact(entry.id)}>
{entry.value}
</option>
))}
</select>
);
}
}
2. 联系行动
我将只关注联系操作,因为程序一几乎相同。
export function readContacts(programId) {
return (dispatch, state) => {
dispatch({ type: 'READ_CONTACTS' });
fetch({ }) // Insert programId in your parameter
.then((response) => dispatch(setContacts(response.data)))
.catch((error) => dispatch(addContactError(error)));
};
}
export function selectContact(id) {
return {
type: 'SELECT_CONTACT',
id,
};
}
export function setContacts(data) {
return {
type: 'SET_CONTACTS',
data,
};
}
export function addContactError(error) {
return {
type: 'ADD_CONTACT_ERROR',
error,
};
}
3. 接触减速器
import { combineReducers } from 'redux';
export default combineReducers({
didInvalidate,
isFetching,
data,
selectedItem,
errors,
});
function didInvalidate(state = true, action) {
switch (action.type) {
case 'SET_PROGRAM': // !!! THIS IS THE TRICK WHEN YOU SELECT ANOTHER PROGRAM, YOU INVALIDATE THE FETCHED DATA !!!
case 'INVALIDATE_CONTACT':
return true;
case 'SET_CONTACTS':
return false;
default:
return state;
}
}
function isFetching(state = false, action) {
switch (action.type) {
case 'READ_CONTACTS':
return true;
case 'SET_CONTACTS':
return false;
default:
return state;
}
}
function data(state = {}, action) {
switch (action.type) {
case 'SET_CONTACTS':
return action.data;
default:
return state;
}
}
function selectedItem(state = null, action) {
switch (action.type) {
case 'SELECT_CONTACT':
return action.id;
case 'READ_CONTACTS':
case 'SET_CONTACTS':
return null;
default:
return state;
}
}
function errors(state = [], action) {
switch (action.type) {
case 'ADD_CONTACT_ERROR':
return [
...state,
action.error,
];
case 'SET_CONTACTS':
return state.length > 0 ? [] : state;
default:
return state;
}
}
希望能帮助到你。