I have a redux thunk createTodoThunk
.
This thunk needs two variables accountIntId
and todoListIntId
required as placeholders to build the URL of the endpoint to call to create the todo.
In practice, I need that an URL changes from this to this:
- /api/accounts/:account/todo_lists/:todo_list/todos
+ /api/accounts/1/todo_lists/1/todos
The question is: how can I pass these two variables to the thunk?
More details about the thunk later.
For the moment lets go in order...
I have a form to create a todo:
const TodoForm = ({ handleSubmit, isWorking, scope, onToggle }) => {
const idPrefix = 'todo';
return (
<form
onSubmit={handleSubmit}
>
<Field
component={RenderField}
name="name"
type="text"
idPrefix={idPrefix}
/>
<Field
component={RenderField}
name="description"
type="textarea"
idPrefix={idPrefix}
/>
<button type="submit">
{'creating' === scope ? 'Create new todo' : 'Edit todo'}
{isWorking && <Spinner />}
</button>
...
</form>
);
};
TodoForm.propTypes = {
...
};
function mapStateToProps(state, ownProps) {
...
return { isWorking };
}
function mapDispatchToProps(dispatch, ownProps) {
...
return { onCancel };
}
const ConnectedForm = connect(mapStateToProps, mapDispatchToProps)(TodoForm);
export default reduxForm({ form: 'todo_quick' })(ConnectedForm);
This component is used by other components that show the form to create the Todo (component TodoForm
).
One of those components is TodoListPage
:
class TodoListPage extends React.Component {
componentDidMount() {
...
}
render() {
const {
currentAccountIntId,
currentTodoListModel,
...
onCreateTodo,
...
} = this.props;
...
return hasToRedirect ? (
...
) : (
...
{... &&
(showTodoForm ? (
<TodoForm
onSubmit={onCreateTodo}
...
/>
) : (
...
))}
...
);
}
}
TodoListPage.propTypes = {
currentAccountIntId: PropTypes.number.isRequired,
currentTodoListIntId: PropTypes.number.isRequired,
...
onCreateTodo: PropTypes.func.isRequired,
...
};
TodoListPage.defaultProps = { currentTodoListModel: null };
const mapStateToProps = (state, ownProps) => {
const currentAccountIntId = parseInt(ownProps.match.params[ACCOUNT_KEY], 10);
const currentTodoListIntId = parseInt(ownProps.match.params[TODO_LIST_KEY], 10);
return {
currentAccountIntId,
currentTodoListIntId,
currentTodoListModel: dbGetTodoListDetailsFromIntId(state, currentTodoListIntId),
...
};
};
const mapDispatchToProps = {
onCreateTodo: createTodoThunk,
...
};
export default connect(mapStateToProps, mapDispatchToProps)(TodoListPage);
As you can see, onSubmit={onCreateTodo}
actually receives the thunk createTodoThunk
(as defined in mapDispatchToProps
).
The redux thunk createTodoThunk
is this:
export function createTodoThunk(todo) {
return (dispatch, getState) => {
dispatch(createTodoLoadingAction(true));
const token = ctxGetUserToken(getState());
return fetch(TODOS_TODO_CREATE_ENDPOINT, token, null, HTTP_POST, todo)
.then((response) => {
...
};
}
This thunk calls the URL TODOS_TODO_CREATE_ENDPOINT
. It is something like this:
/api/accounts/:account/todo_lists/:todo_list/todos
As you can see, it has two placeholders:
:account
:todo_list
So, before calling the endpoint, I need to substitute the two endpoints.
The fetch()
function already does this: it is sufficient to pass an array with the substitutions to do:
export function createTodoThunk(todo) {
return (dispatch, getState) => {
dispatch(createTodoLoadingAction(true));
const token = ctxGetUserToken(getState());
+ const placeholders = [
+ { replace: "account", value: accountIntId },
+ { replace: "todo_list", value: todoListIntId },
+ ];
- return fetch(TODOS_TODO_CREATE_ENDPOINT, token, null, HTTP_POST, todo)
+ return fetch(TODOS_TODO_CREATE_ENDPOINT, token, placeholders, HTTP_POST, todo)
.then((response) => {
...
};
}
So, the question is: how do I pass accountIntId
and todoListIntId
to createTodoThunk()
?
Ideally, I'd like to create a method in TodoForm
that actually wraps createTodoThunk
passing it the two arguments accountIntId
and todoListIntId
.
Unfortunately, after a lot of try and fails, I'm writing here because I'm not able to find a proper solution.
Any ideas?