Reactjs 当多个组件为其使用复杂对象的部分时,redux如何工作';s源
我有一个对象(这是一个属性数组,因为它是动态的,所以我不能将它拆分为多个属性),我将其保存在reducer中,看起来像这样:Reactjs 当多个组件为其使用复杂对象的部分时,redux如何工作';s源,reactjs,react-native,redux,react-redux,Reactjs,React Native,Redux,React Redux,我有一个对象(这是一个属性数组,因为它是动态的,所以我不能将它拆分为多个属性),我将其保存在reducer中,看起来像这样: [ {type: list, elements: []} {type: map, elements: []} {type: wheelList, elements: []} {type: chart, elements: []} {type: dyna, elements: []} ... ] { isFetching: false, d
[
{type: list, elements: []}
{type: map, elements: []}
{type: wheelList, elements: []}
{type: chart, elements: []}
{type: dyna, elements: []}
...
]
{
isFetching: false,
didInvalidate: false,
data: [
{ type: 'list', id: 1, name: 'test' },
{ type: 'list', id: 2, name: 'test1' },
{ type: 'map', id: 3, name: 'test' },
{ type: 'map', id: 4, name: 'test1' },
{ type: 'list', id: 5, name: 'test' },
{ type: 'list', id: 6, name: 'test1' },
{ type: 'list', id: 7, name: 'test' },
{ type: 'list', id: 8, name: 'test1' },
]
}
在一个组件中,我从存储中获取并访问它,如下所示:
this.props.allElements
然后,我为每个组件呈现不同的组件(伪代码):
减速器:
export default function (state:State = initialState, action:Action): State {
if (action.type === 'ELEMENTS_RECEIVED') {
return {
...state,
allElements: action.allElements,
};
在大组件中:
const mapStateToProps = state => ({
allElements: state.main.allElements
...
class Main extends Component {
...
componentDidMount() {
// here I actually make a call to get data
}
...
render() {
return (
// Here is the big code
// Loop over props.allElements
// and render it in different way based on data inside each element
)
}
数据示例:
[
{
"type": "list",
"count": 99,
"elements": [
{
"id": 1,
"name": "test"
},
{
"id": 2,
"name": "test1"
}
]
},
{
"type": "map",
"count": 99,
"elements": [
{
"id": 3,
"name": "test"
},
{
"id": 4,
"name": "test1"
}
]
},
{
"type": "list",
"count": 99,
"elements": [
{
"id": 5,
"name": "test"
},
{
"id": 6,
"name": "test1"
}
]
},
{
"type": "list",
"count": 99,
"elements": [
{
"id": 7,
"name": "test"
},
{
"id": 8,
"name": "test1"
}
]
}
]
您可以在
thunk
操作
中执行循环,并将数据拆分为单独的缩减器
您的操作可以如下所示:
// action thunk
export function getScreenElements() {
return function (dispatch) {
// get data from server here
const dataFromServer = fetch('url');
// do your looping here and dispatch each data acording to its type
dataFromServer.map(obj => {
switch (obj.type) {
case 'list':
dispatch({
type: 'LIST_RECEIVED',
listElements: obj
});
case 'map':
dispatch({
type: 'MAP_RECEIVED',
mapElements: obj
});
// ....
}
});
}
}
// map reducer
export default function map(state = initialState, action) {
if (action.type === 'MAP_RECEIVED') {
return {
...state,
mapElements: action.mapElements,
}
}
}
// list reducer
export default function list(state = initialState, action) {
if (action.type === 'LIST_RECEIVED') {
return {
...state,
listElements: action.listElements,
}
}
}
// inside your component render mehtod
render(){
const { list, map } = this.props; // redux data passed as props from the seperate reducers
return (
<div>
<ListComponent elements={list}>
<MapComponent elements={map}>
</div>
);
}
您的单独减速机可能看起来像这样:
// action thunk
export function getScreenElements() {
return function (dispatch) {
// get data from server here
const dataFromServer = fetch('url');
// do your looping here and dispatch each data acording to its type
dataFromServer.map(obj => {
switch (obj.type) {
case 'list':
dispatch({
type: 'LIST_RECEIVED',
listElements: obj
});
case 'map':
dispatch({
type: 'MAP_RECEIVED',
mapElements: obj
});
// ....
}
});
}
}
// map reducer
export default function map(state = initialState, action) {
if (action.type === 'MAP_RECEIVED') {
return {
...state,
mapElements: action.mapElements,
}
}
}
// list reducer
export default function list(state = initialState, action) {
if (action.type === 'LIST_RECEIVED') {
return {
...state,
listElements: action.listElements,
}
}
}
// inside your component render mehtod
render(){
const { list, map } = this.props; // redux data passed as props from the seperate reducers
return (
<div>
<ListComponent elements={list}>
<MapComponent elements={map}>
</div>
);
}
然后您可以这样渲染它:
// action thunk
export function getScreenElements() {
return function (dispatch) {
// get data from server here
const dataFromServer = fetch('url');
// do your looping here and dispatch each data acording to its type
dataFromServer.map(obj => {
switch (obj.type) {
case 'list':
dispatch({
type: 'LIST_RECEIVED',
listElements: obj
});
case 'map':
dispatch({
type: 'MAP_RECEIVED',
mapElements: obj
});
// ....
}
});
}
}
// map reducer
export default function map(state = initialState, action) {
if (action.type === 'MAP_RECEIVED') {
return {
...state,
mapElements: action.mapElements,
}
}
}
// list reducer
export default function list(state = initialState, action) {
if (action.type === 'LIST_RECEIVED') {
return {
...state,
listElements: action.listElements,
}
}
}
// inside your component render mehtod
render(){
const { list, map } = this.props; // redux data passed as props from the seperate reducers
return (
<div>
<ListComponent elements={list}>
<MapComponent elements={map}>
</div>
);
}
//在组件渲染方法中
render(){
const{list,map}=this.props;//redux数据作为props从单独的还原器传递
返回(
);
}
编辑作为您评论的后续内容: 如果我将allData放入父对象,并将allData.xyz传递给渲染中的组件 当任何数据更改时,父级也将按其道具的状态重新播放 改变 嗯,重新呈现父对象并没有什么错。当
组件的render
方法运行时,并不意味着它将重新渲染到物理DOM
,它将更新或覆盖虚拟DOM
的对象,然后通过检查物理DOM
与虚拟DOM
之间的差异,以确定何时,物理的DOM
应该如何以及在哪里更新。
它只能更新DOM
元素的某些属性,而无需重新渲染它们
您还可以选择,但我强烈建议您不要这样做。在您的数据示例中,有多个项目具有相同的类型(例如:列表)
Redux不建议使用这种嵌套对象,因为您将无法优化渲染,也无法优化数据失效
优化的一种方法是将数据展平,使其看起来像这样:
[
{type: list, elements: []}
{type: map, elements: []}
{type: wheelList, elements: []}
{type: chart, elements: []}
{type: dyna, elements: []}
...
]
{
isFetching: false,
didInvalidate: false,
data: [
{ type: 'list', id: 1, name: 'test' },
{ type: 'list', id: 2, name: 'test1' },
{ type: 'map', id: 3, name: 'test' },
{ type: 'map', id: 4, name: 'test1' },
{ type: 'list', id: 5, name: 'test' },
{ type: 'list', id: 6, name: 'test1' },
{ type: 'list', id: 7, name: 'test' },
{ type: 'list', id: 8, name: 'test1' },
]
}
app.js
class App extends React.Component {
render() {
return (
<div>
<ListComponent />
<MapComponent />
</div>
);
}
}
ListComponent.js
class App extends React.Component {
render() {
return (
<div>
<ListComponent />
<MapComponent />
</div>
);
}
}
这里的技巧是只传递元素id
,并让子元素检查何时重新加载
请注意,ListComponent
仅当listElements
值中有任何修改时才会重新加载。
示例:
- 现在有一个“列表”类型的新项
- 有一个“列表”类型的已删除项
- 已修改当前“列表”项目之一
代码:
请记住,API可能会以某种方式向您发送格式化的数据,但您可以根据需要重新格式化它们
一篇关于此类优化的有趣文章:
如果您想在redux中进一步使用数据规范化最佳实践:
希望有帮助。那你为什么不把它分成不同的减速机呢?我真的能从中受益吗?这是我从服务器获取的对象,它是非常动态的。这就是为什么我要求解释react将如何处理这种情况。我认为在渲染
中执行此操作不如在thunk
(action creator)中执行此循环,并将每个类型
分配到不同的减速机
。您能给我一些指导或示例,在我的情况下如何执行此操作?我真的不明白如何分割它。现在我循环遍历所有元素,从中提取元素并进行渲染。现在一切都在一个属性中。正如我所说的,只有map经常更新,因为它会重新渲染。好的,发布您的操作和还原程序,以这种方式获取并传递this.props.allegements
。如果地图更新列表将不会重新渲染和相反。是的,不会重新渲染,如果没有新的道具或状态改变内部我明白了。但我会等着接受答案。如果我得到3个列表和3个地图作为响应,这个解决方案就帮不了我。每个AN都需要不同的减速器。或者我错了,这可以应用到这个问题上。这和你现在在这个方面所做的没有什么不同。我只是将组件外部的逻辑移到了redux流。如果每个对象都是一个数组,那么reducer的数据结构就是一个数组,你也可以映射到它上面。对不起,你能更新一下答案吗?如果我看到它,我会更好地理解它。假设你有3个列表和一张地图。顺便说一句,感谢您的帮助:-)