问题
In React itself, I have the function getTodos(), in which it calls another functiongetTodo(). It passes res.data[0].id to the getTodo() function.
React
Demo here: https://stackblitz.com/edit/react-qvsjrz
Code below:
class App extends Component {
constructor() {
super();
this.state = {
todos: [],
todo: {}
};
}
componentDidMount() {
this.getTodos()
}
getTodos = () => {
axios({
url: 'https://jsonplaceholder.typicode.com/todos',
method: 'GET'
})
.then(res => {
this.setState({
todos: res.data,
}, () => this.getTodo(res.data[0].id))
})
.catch(error => {
console.log(error);
});
};
getTodo = (todoId) => {
axios({
url: `https://jsonplaceholder.typicode.com/todos/${todoId}`,
method: 'GET'
})
.then(res => {
this.setState({
todo: res.data
})
})
.catch(error => {
console.log(error);
})
}
render() {
console.log(this.state.todo);
return (
<div>
</div>
);
}
}
The above code tries to convert to react + redux.
React + redux
In actions, I declared two functions getTodo andgetTodos. Could someone advise me on how to call the getTodo function in thegetTodos function by passing the getTodo id function?
Demo here: https://stackblitz.com/edit/react-ewpquh?file=actions%2Findex.js
actions
import axios from 'axios';
export const GET_TODOS = 'GET_TODOS';
export const FETCH_SUCCESS = 'FETCH_SUCCESS';
export const FETCH_FAILURE = 'FETCH_FAILURE';
export const getTodos = () =>
dispatch => {
return axios({
url: 'https://jsonplaceholder.typicode.com/todos',
method: 'GET',
})
.then(({data})=> {
console.log(data);
dispatch({type: GET_TODOS, payload:{
data
}});
})
.catch(error => {
console.log(error);
dispatch({type: FETCH_FAILURE})
});
};
export const getTodo = () =>
dispatch => {
return axios({
url: 'https://jsonplaceholder.typicode.com/todos',
method: 'GET',
})
.then(({data})=> {
console.log(data);
dispatch({type: GET_TODOS, payload:{
data
}});
})
.catch(error => {
console.log(error);
dispatch({type: FETCH_FAILURE})
});
};
Todos
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {getTodos} from '../.././actions';
class Todos extends Component {
componentDidMount() {
this.props.getTodos();
}
render() {
return (
<ul>
{this.props.todos.map(todo => {
return <li key={todo.id}>
{todo.title}
</li>
})}
</ul>
);
}
}
const mapStateToProps = state => {
console.log(state.todos);
const { todos } = state;
return {
todos
};
};
const mapDispatchToProps = dispatch => ({
getTodos: () => dispatch(getTodos())
});
export default connect(mapStateToProps, mapDispatchToProps)(Todos);
reducers
import {GET_TODOS} from '../../actions';
const initialState = {
todos: []
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case 'GET_TODOS':
return {
...state,
todos: action.payload.data
};
default:
return state;
}
};
export default rootReducer;
store
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';
const store = createStore(rootReducer, applyMiddleware(thunk));
export default store;
回答1:
Instead of over-complicating your actions, you should have separate action types for different APIs.
- GET_TODOS - For /todos API
- GET_TO - For /todos/ API
To add getTodo method with ID, this is how I solved it -
- For each
litag, add anonClickthat calls yourgetTodoAPI. (This is done as an example for the sake of addinggetTodoin the workflow.
return <li key={todo.id} onClick={() => this.handleClick(todo.id)}>
- Add
handleClickwhich callsgetTodomethod from props.- First add
getTodoin your componentsmapDispatchToProps:
- First add
import { getTodo, getTodos} from '../.././actions';
const mapDispatchToProps = dispatch => ({
getTodos: () => dispatch(getTodos()),
getTodo: id => dispatch(getTodo(id))
});
- Add
handleClick-
handleClick = id => {
this.props.getTodo(id).then(() => {
console.log(`You Clicked: ${JSON.stringify(this.props.todo)}`)
})
}
- Update your
getTodoaction to take ID as input:
NOTE: The added GET_TODO type
export const getTodo = (id) => dispatch => {
return axios({
url: `https://jsonplaceholder.typicode.com/todos/${id}`,
method: 'GET',
})
.then(({data})=> {
// console.log(data);
dispatch({type: GET_TODO, payload: data});
})
.catch(error => {
console.log(error);
dispatch({type: FETCH_FAILURE})
});
};
- Separate out your reducers into
todosandtodoand usecombineReducersfromreduxpackage -
const todos = (state = [], action) => {
const { type, payload } = action;
switch(type) {
case 'GET_TODOS':
return payload;
default:
return state;
}
}
const todo = (state = {}, action) => {
const { type, payload } = action;
switch(type) {
case 'GET_TODO':
return payload;
default:
return state;
}
}
const rootReducer = combineReducers({todos, todo});
- Run the app and click on any item in the todo list. Console log for the clicked todo item is shown when API response for that ID is fetched.
The live sandbox is available here - https://stackblitz.com/edit/react-ndkasm
来源:https://stackoverflow.com/questions/58214170/calling-one-function-in-another-and-passing-it-id-react-redux