我有一个关于如何在axios中添加第二个嵌套api查询的问题。第二个api查询基于第一个api数组json中的id获取json对象。然后在函数Retrieve()中连接到全局数组?
第一个api网址:
'/api/sets'
第二个api子级:
'/api/sets/' + todo.id + '/tasks'
从第一个API网址响应全局json:
[
{
"id": 121,
"name": "list1",
"description": "description1"
},
{
"id": 9,
"name": "list2",
"description": "description2"
}
]
通过ID第一API响应来自API的第二个JSON子级:
[
{
"id": 1,
"name": "task1",
"description": "description task1"
},
{
"id": 2,
"name": "task2",
"description": "description task2"
}
]
,最后期望合并的存储数组json
[
{
"id": 121,
"name": "list1",
"description": "description1",
"task": [{
"id": 1,
"name": "task1",
"description": "description task1"
},
{
"id": 2,
"name": "task2",
"description": "description task2"
}
]
},
{
"id": 9,
"name": "list2",
"description": "description2",
"task": [{
"id": 10,
"name": "task1",
"description": "description task1"
},
{
"id": 11,
"name": "task2",
"description": "description task2"
}
]
}
]
代码js: index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'mobx-react';
import TodoStore from './store';
const Root = (
<Provider TodoStore={TodoStore}>
<App />
</Provider>
);
ReactDOM.render(Root, document.getElementById('root'));
store.js
import React from 'react';
import { observable, action, configure, runInAction } from 'mobx';
import axios from 'axios';
configure({ enforceActions: 'observed' });
class TodoStore {
@observable todos = [];
@action Retrieve = () => {
axios
.get('/api/sets')
.then(response => {
let tempTodos = response.data;
runInAction(() => {
this.todos = tempTodos;
});
})
.catch(error => {
console.log(error);
});
};
}
const store = new TodoStore();
export default store;
app.js
import React, { Component } from 'react';
import TodoItem from './TodoItem';
import { toJS } from 'mobx';
import { inject, observer } from 'mobx-react';
@inject('TodoStore')
@observer
class App extends Component {
render() {
const TodoStore = this.props.TodoStore;
console.log(toJS(TodoStore.todos));
return (
<div className="App">
<div className="Todo-container">
{TodoStore.todos.map(todo => (
<TodoItem key={todo.id} todo={todo} />
))}
</div>
</div>
);
}
componentDidMount() {
this.props.TodoStore.Retrieve();
}
}
export default App;
TodoItem.js
import React from 'react';
import PropTypes from 'prop-types';
import { inject, observer } from 'mobx-react';
const TodoItem = inject('TodoStore')(
observer(props => {
const TodoStore = props.TodoStore;
return (
<>
<div key={props.todo.id} className="todo-item">
<span>{props.todo.id}</span>
<h5>{props.todo.name}</h5>
<p>{props.todo.description}</p>
<ul className="list-item">
<li>list-item id?</li>
<li>list-item id?</li>
<li>list-item id?</li>
</ul>
</div>
</>
);
})
);
TodoItem.wrappedComponent.propTypes = {
todo: PropTypes.object.isRequired,
TodoStore: PropTypes.object.isRequired
};
export default TodoItem;
答案 0 :(得分:0)
如果您的API不支持GraphQL端点,那么您必须扩展Retrive()操作并对结点ID进行额外的XHR请求,以合并来自API端点1和2的结果。
@action Retrieve = () => {
axios
.get('/api/sets')
.then(response => {
let tempTodos = response.data;
let todosWithTasks = tempTodos.map(todo => {
let tasks = null;
axios.get('/api/sets/' + todo.id + '/tasks')
.then(response2 => {
tasks = response2.data;
}).catch(error => {
console.log(error);
});
todo.task = tasks;
return todo;
});
// `todosWithTasks` is joined API1 and API2
})
.catch(error => {
console.log(error);
});
};
答案 1 :(得分:0)
多谢了,所有api都加入了,现在我还有另一个小问题。如果在控制台日志键@observable.ref todos = [];
中设置@observable.shallow todos = [];
或task
,则退出并带有对象数组,但是当我设置@observable todos = [];
键task
时不存在。
console.log
(2) [{…}, {…}]
0:
description: "false"
id: 121
name: "list1"
task: Array(2)
0: {id: 10, name: "task1", description: "description task1", state: false, position: 1}
1: {id: 11, name: "task2", description: "description task2", state: true position: 2}
length: 2
__proto__: Array(0)
__proto__: Object
1:
description: "false"
id: 9
name: "list2"
task: Array(2)
0: {id: 3, name: "task1", description: "description task1", state: false, position: 3}
1: {id: 7, name: "task2", description: "description task2", state: false, position: 5}
length: 2
__proto__: Array(0)
__proto__: Object
length: 2
__proto__: Array(0)
,如果尝试使用地图键task
index.module.js:206 Uncaught TypeError: Cannot read property 'map' of undefined
at eval (TodoItem.jsx:17)
at eval (index.module.js:220)
at eval (index.module.js:198)
at trackDerivedFunction (mobx.module.js:1212)
at Reaction.track (mobx.module.js:1752)
at useObserver (index.module.js:196)
at wrappedComponent (index.module.js:220)
at renderWithHooks (react-dom.development.js:12938)
at updateFunctionComponent (react-dom.development.js:14627)
at updateSimpleMemoComponent (react-dom.development.js:14573)
react-dom.development.js:17117 The above error occurred in the <wrappedComponent> component:
in wrappedComponent (created by n)
in n (created by inject-with-TodoStore(Object))
in inject-with-TodoStore(Object) (created by App)
in div (created by App)
in App (created by n)
in n (created by inject-with-TodoStore(App))
in inject-with-TodoStore(App)
in e
code index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import { Provider } from 'mobx-react';
import TodoStore from './TodoStore';
import registerServiceWorker from './registerServiceWorker';
const Root = (
<Provider TodoStore={TodoStore}>
<App />
</Provider>
);
ReactDOM.render(Root, document.getElementById('root'));
registerServiceWorker();
TodoStore.js
import React from 'react';
import {observable, action, computed, configure, runInAction} from 'mobx';
import axios from 'axios';
axios.defaults.baseURL = 'api';
configure({ enforceActions: 'observed' });
class TodoStore {
@observable.shallow todos = [];
@action Retrieve = () => {
axios
.get('/sets')
.then(response => {
let tempTodos = response.data;
let todosWithTasks = tempTodos.map(todo => {
let tasks = null;
axios
.get('/sets/' + todo.id + '/tasks')
.then(response2 => {
todo.task = response2.data;
})
.catch(error => {
console.log(error);
});
return todo;
});
runInAction(() => {
this.todos = todosWithTasks;
});
})
.catch(error => {
console.log(error);
});
};
}
const store = new TodoStore();
export default store;
app.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import TodoItem from './TodoItem';
import { toJS } from 'mobx';
import { inject, observer } from 'mobx-react';
@inject('TodoStore')
@observer
class App extends Component {
render() {
const TodoStore = this.props.TodoStore;
console.log(toJS(TodoStore.todos));
return (
<div className="App">
{TodoStore.todos.map(todo => (
<TodoItem key={todo.id} todo={todo} />
))}
</div>
);
}
async componentDidMount() {
this.props.TodoStore.Retrieve();
}
}
TodoItem.wrappedComponent.propTypes = {
todo: PropTypes.object.isRequired,
TodoStore: PropTypes.object.isRequired
};
export default App;
todoitem
import React from 'react';
import PropTypes from 'prop-types';
import { inject, observer } from 'mobx-react';
import TodoItemTask from './TodoItemtask';
const TodoItem = inject('TodoStore')(
observer(props => {
const TodoStore = props.TodoStore;
return (
<>
<div key={props.todo.id} className="todo-item">
<span>{props.todo.id}</span>
<h5>{props.todo.name}</h5>
<p>{props.todo.description}</p>
{props.todo.task.map((item, index) => (
<TodoItemTask key={index + item.id} item={item} />
))}
</div>
</>
);
})
);
TodoItem.wrappedComponent.propTypes = {
todo: PropTypes.object.isRequired,
TodoStore: PropTypes.object.isRequired
};
export default TodoItem;
TodoItemTask.js
import React from 'react';
import PropTypes from 'prop-types';
import { inject, observer } from 'mobx-react';
const TodoItemTask = inject('TodoStore')(
observer(props => {
const TodoStore = props.TodoStore;
return (
<>
<div key={props.item.id} className="todo-item">
<span>{props.index}</span>
<p>{props.item.name}</p>
<p>{props.item.description}</p>
</div>
</>
);
})
);
TodoItemTask.wrappedComponent.propTypes = {
item: PropTypes.object.isRequired,
TodoStore: PropTypes.object.isRequired
};
export default TodoItemTask;
没有错误,如果设置了静态数据,则呈现所有数据
@observable todos = [
{
"id": 121,
"name": "list1",
"description": "description1",
"task": [{
"id": 1,
"name": "task1",
"description": "description task1"
},
{
"id": 2,
"name": "task2",
"description": "description task2"
}
]
},
{
"id": 9,
"name": "list2",
"description": "description2",
"task": [{
"id": 10,
"name": "task1",
"description": "description task1"
},
{
"id": 11,
"name": "task2",
"description": "description task2"
}
]
}
];
答案 2 :(得分:0)
实际上,这不是mobx的问题,我发现此函数中错误地连接了两个api url json。
在console.log(todosWithTasks)
中看起来不错,但是console.log (JSON.stringify(todosWithTasks))
却不正确。
这是实际代码
import React from 'react';
import {observable, action, computed, configure, runInAction} from 'mobx';
import axios from 'axios';
axios.defaults.baseURL = 'api';
configure({ enforceActions: 'observed' });
class TodoStore {
@observable todos = [];
@action async Retrieve = () => {
this.isLoading = true;
await axios
.get('/sets')
.then(async response => {
let tempTodos = response.data;
tempTodos.forEach(todo => (todo.task = []));
let todosWithTasks = tempTodos.map(todo => {
axios
.get('/sets/' + todo.id + '/tasks')
.then(response2 => {
todo.task = response2.data;
return todo;
})
.catch(error => {
console.log(error);
});
return todo;
});
runInAction(() => {
console.log(todosWithTasks);
console.log(JSON.stringify(todosWithTasks));
this.todos = todosWithTasks;
});
})
.catch(error => {
console.log(error);
});
};
}
const store = new TodoStore();
export default store;
console.log(JSON.stringify(todosWithTasks))的输出
[{"id":1,"name":"list1","description":"description1","task":[]}]
console.log(todosWithTasks)的输出看起来很好
(1) [{…}]
0:
description: "description1"
id: 1
name: "list1"
task: Array(1)
0: {id: 1, name: "task1", description: "description task1"}
length: 1
__proto__: Array(0)
__proto__: Object
length: 1
__proto__: Array(0)
因此,它不会在map函数中呈现,因为key task
为空。
如果修改后的合并json文件为localy,则在axios中一切正常。在console.log(JSON.stringify(todosWithTasks))中,一切正常。
@action Retrieve() {
axios
.get('localhost:3000/src/data.json')
.then(response => {
let tempTodos = response.data;
tempTodos.forEach(todo => (todo.editing = false));
runInAction(() => {
this.todos = tempTodos;
console.log(JSON.stringify(tempTodos));
});
})
.catch(error => {
console.log(error);
});
}