mo_*_*aat 1 reactjs react-redux
调用调度以获取 React 组件的初始数据的最佳方法是什么。我的理解是 ComponentWillMount 在渲染之前被调用。所以理论上,如果我在 ComponentWillMount 上调用 dispatch,当我点击渲染然后 ComponentDidMount 时,我应该在组件的道具中拥有我的数据,对吧?我没有看到。
我看到 render 被调用了两次,并且在初始化组件时第一次调用时,我无法访问 props 中的数据。似乎在第二次渲染之前实际上并没有调用 dispatch 。我基本上希望了解在最初设置组件时调用调度的最佳方式。我基本上是在尝试执行以下操作,其中我使用容器组件从调度中获取数据,然后将其作为道具传递给子组件。但我也想在 ContainerComponent 中初始化一些状态变量,然后将它们作为 props 传递给 ChildComponent。问题是我想要初始化的状态变量取决于从调度返回的数据,理想情况下我会在 ComponentWillMount 或 ComponentDidMount 中进行初始化。
import React from 'react';
import axios from 'axios';
import { connect } from 'react-redux';
import ChildComponent from './ChildComponent.js';
import { getTransactionsAll } from '../actions/actions.js';
class ContainerComponent extends React.Component {
constructor() {
super();
this.state = {
acctList:[],
acctChecked:[],
categoryList:[]
}
}
componentWillMount() {
console.log("componentWillMount entered");
this.props.get_data();
console.log(this.props.searchProps.transactions_all);//this is undefined meaning the dispatch has not assigned the data yet...??
}
componentDidMount() {
console.log("componentDidMount entered");
console.log(this.props.searchProps.transactions_all);//this is undefined meaning the dispatch has not assigned the data yet...??
}
render() {
console.log("TransactionManagerContainer render entered");
console.log(this.props.searchProps.transactions_all);//this is undefined the first time around meaning the dispatch has not assigned the data yet...??, but is defined on the second call to render after the dispatch has actually occurred...
return <ChildComponent
data={this.props.searchProps.data}/>;
}
const mapStateToProps = (state) => ({
searchProps: state.searchProps
});
export default connect(mapStateToProps, {getTransactionsAll})(TransactionManagerContainer);
Run Code Online (Sandbox Code Playgroud)
这是我分配状态的减速器:
import { combineReducers } from 'redux'
import {GET_TRANSACTIONS } from '../actions/actions.js'
import {GET_TRANSACTIONS_ALL } from '../actions/actions.js'
const INITIAL_STATE = { defaultYear: 2016, transactions: []};
function get_transactions(state = INITIAL_STATE, action) {
// console.log("this is in the reducer: get_transactions");
// console.log(action);
switch(action.type) {
case GET_TRANSACTIONS:
// return { ...state, transactions: action.payload };
return Object.assign({}, state, {
transactions: action.payload,
selectedYear: action.selectedYear
})
default:
return state;
}
}
function get_transactions_all(state = INITIAL_STATE, action) {
console.log("this is the value of action in the reducer: get_transactions_all");
console.log(action);
switch(action.type) {
case GET_TRANSACTIONS_ALL:
// return { ...state, transactions: action.payload };
return Object.assign({}, state, {
transactions_all: action.payload
})
console.log("this is the value of state in the reducer after being set");
console.log(state);
default:
return state;
}
}
const rootReducer = combineReducers({
//stateProps: get_transactions,
searchProps: get_transactions_all
})
export default rootReducer
Run Code Online (Sandbox Code Playgroud)
以下是我的行动:
import axios from 'axios';
export const GET_TRANSACTIONS = 'GET_TRANSACTIONS';
export function getTransactions(year) {
return function(dispatch) {
axios.get(`http://localhost:3001/api/transfilter?year=${year}&grouping=2`)
.then(response => {
dispatch({
type: GET_TRANSACTIONS,
payload: response.data,
selectedYear: year
});
})
.catch((error) => {
console.log(error);
})
}
}
export const GET_TRANSACTIONS_ALL = 'GET_TRANSACTIONS_ALL';
export function getTransactionsAll(year) {
return function(dispatch) {
axios.get(`http://localhost:3001/api/trans?limit=20`)
.then(response => {
dispatch({
type: GET_TRANSACTIONS_ALL,
payload: response.data
});
})
.catch((error) => {
console.log(error);
})
}
}
Run Code Online (Sandbox Code Playgroud)
我相信你的主要问题是:
调用调度以获取 React 组件的初始数据的最佳方法是什么?
获取初始数据请求(或任何一般的 AJAX 请求)应该进入componentDidMount生命周期事件。
这有几个原因,这里有两个重要的:
Fiber 是 React 协调算法的下一个实现,将能够根据需要启动和停止渲染以提高性能。这样做的一个权衡是 componentWillMount,另一个生命周期事件,在其中发出 AJAX 请求可能是有意义的,将是“非确定性的”。这意味着 React 可能会在需要时在不同时间开始调用 componentWillMount。对于 AJAX 请求来说,这显然是一个糟糕的公式。
您不能保证在组件安装之前 AJAX 请求不会解决。如果是这样,那将意味着您将尝试在未挂载的组件上设置状态,这不仅不起作用,而且 React 会为此大喊大叫。在 componentDidMount 中执行 AJAX 将保证有一个要更新的组件。
然后,您提出了很多较小的问题,我很难回答所有问题,但我会尽量涵盖大部分:
undefined在componentWillMount和 中componentDidMount。那只是因为数据还没有到达;undefined在组件的第一次呈现期间是正常的。初始渲染发生在数据到达之前;dispatch触发器的异步数据提取。在数据到来之后, areducer被击中并且组件被重新渲染(这是第二次重新渲染)。如果主组件中的子组件需要数据 -render如果数据存在,则检查父方法有条件地传递内部组件,仅当数据存在时。像这样:
class ContainerComponent extends React.Component {
// ... omitted for brevity
render() {
return (
{ this.props.searchProps.data ?
<ChildComponent
data={this.props.searchProps.data} />
: <p>Loading</p>
}
);
}
}
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
3461 次 |
| 最近记录: |