Passing multiple params in Redux Toolkit's createAsyncThunk - reactjs

I have the following code where I want to send POST request in with a data object and a history function. How can I pass the history param in the action creator? Thanks
login action creator
import { createAsyncThunk } from '#reduxjs/toolkit';
import { client } from '../client';
import {User} from './userLoginSlice';
export const userLogin = createAsyncThunk('user/userLogin' , async (data: User, history: string, thunkAPI) => {
try {
const res = await client.post<User>('/User/Credentials/Login', data);
if(res.status === 200) history.push('/dashboard');
return res.data;
} catch (error) {
return thunkAPI.rejectWithValue('Sorry! Something went wrong ):') ;
}
});
login slice
import { createSlice } from '#reduxjs/toolkit';
import { userLogin } from './userLoginThunk';
export interface User{
email: string;
passowrd: string;
rememberMe: boolean;
}
const initialState = {
user: {} as User,
loading: false,
error: ''
};
export const userLoginSlice = createSlice({
name: 'user',
initialState: initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(userLogin.pending, (state) => {
state.loading = true;
state.error = '';
});
builder.addCase(userLogin.fulfilled, (state, { payload }) => {
state.loading = false;
state.user = payload;
});
builder.addCase(userLogin.rejected, (state, { payload }) => {
state.loading = false;
state.error = String(payload);
});
}
});
export const userLoginReducer = userLoginSlice.reducer;
Using the action creator in a component
import { Form, Input, Checkbox } from 'antd';
import { useHistory } from 'react-router-dom';
import { ConfirmBtn } from '../small-components/ActionBtns';
import { useAppDispatch } from '../../custom-hooks/reduxCustomHooks';
import {userLogin } from 'src/redux/user-login/userLoginThunk';
import {User} from '../../redux/user-login/userLoginSlice';
import '../../sass/light-theme/user-login.scss';
export const UserLogin = () => {
const dispatch = useAppDispatch();
const history = useHistory();
const onFinish = (values: User) => {
dispatch(userLogin(values, history));
};
return (
<Form></Form>
);
};
It's throwing the error which says that the userLogin expects 1 arguments but got 2. What am I doing wrong?

A thunk only accepts one parameter, so you would have to provide an object containing both your values and the history object.
In your case, you could also use the the unwrap() function (https://stackoverflow.com/a/67876542/3170628) so you don't have to provide the history object to your thunk:
const onFinish = async (values: User) => {
try {
await dispatch(userLogin(values)).unwrap();
history.push('/dashboard');
} catch (error) {
...
}
};

Related

How can I await for an async action dispatch on the click of a button?

I have this react component where in the user wants to send in a login request but whenever I dispatch the action, even before it is executed the further code in my component is executed.
I've tried making the login request function as async and even tried using await before dispatching the action but it's all been in vain.
Component file:
import React from 'react';
import BaseButton from '../BaseButton/BaseButton';
import { useState } from 'react';
import { userLogin } from '../../redux/auth/authActions';
import axios from 'axios';
import {connect} from 'react-redux'
function Login({ isLoggedIn, userLogin }) {
const [login, setLogin] = useState(true); //to see if the user wats to login or sign up
const [email, setEmail] = useState("");
const [name, setName] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const handleLogin = () => {
let userCredentials = {
email: email,
password: password
}
userLogin(userCredentials); // <------ i want to wait for this to execute before the below code is executed
if (isLoggedIn) {
console.log('im here');
} else {
console.log('wrong credentials');
}
}
const handleSignUp = async () => {
}
return login ? (
<>
{*/ ...some JSX for user input */}
<div className="flex justify-center">
<BaseButton variant={'solid'} onClick = {handleLogin}>Submit</BaseButton>
</div>
{*/ ...some more JSX for user input */}
<>
}
const mapStateToProps = (state) => {
return {
isLoggedIn: state.auth.isLoggedIn
}
}
const dispatchStateToProps = (dispatch) => {
return {
userLogin: (userCredentials) => dispatch(userLogin(userCredentials))
}
}
export default connect(mapStateToProps, dispatchStateToProps)(Login);
authActions:
import {
USER_LOGIN_REQUEST,
USER_LOGIN_SUCCESS,
USER_LOGIN_FAILURE,
} from './authTypes';
import axios from 'axios';
export const sendLoginRequest = () => {
return {
type: USER_LOGIN_REQUEST,
};
};
export const loginSucccess = () => {
return {
type: USER_LOGIN_SUCCESS,
};
};
export const loginFailure = (error) => {
return {
type: USER_LOGIN_FAILURE,
payload: error,
};
};
export const userLogin = (userCredentials) => {
return (dispatch) => {
try {
dispatch(sendLoginRequest());
axios
.post('http://localhost:3001/auth/login', userCredentials)
.then((data) => {
console.log(data.status);
dispatch(loginSucccess());
})
.catch(err => {
console.log("incorrect credentials");
dispatch(loginFailure('incorrect credentials'));
});
} catch(err) {
dispatch(loginFailure(err.message));
}
};
};
auth reducer file:
import {
USER_LOGIN_REQUEST,
USER_LOGIN_FAILURE,
USER_LOGIN_SUCCESS,
} from './authTypes';
const initialState = {
loading: false,
isLoggedIn: false,
error: ''
};
const authReducer = (state = initialState, action) => {
switch (action.type) {
case USER_LOGIN_REQUEST:
return {
...state,
loading: true
}
case USER_LOGIN_SUCCESS: return{
...state,
loading: false,
isLoggedIn: true,
}
case USER_LOGIN_FAILURE: return{
...state,
loading: false,
isLoggedIn: false,
error: action.payload
}
default: return state;
}
};
export default authReducer;
my store file:
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';
import rootReducer from '../rootReducer';
const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk)));
export default store;
root reducer:
import {combineReducers} from 'redux';
import authReducer from './auth/authReducer';
const rootReducer = combineReducers({
auth: authReducer
});
export default rootReducer;
The userLogin action isn't declared async nor does it return a Promise so this is why your handleLogin handler isn't able to wait for it to complete.
Convert userLogin to an async action function.
export const userLogin = (userCredentials) => async (dispatch) => {
try {
dispatch(sendLoginRequest());
const data = await axios.post('http://localhost:3001/auth/login', userCredentials);
console.log(data.status);
dispatch(loginSucccess());
return true; // <-- return resolved value
} catch(err) {
dispatch(loginFailure(err.message));
return false; // <-- return resolved value
}
};
Convert handleLogin to an async function so it can await the dispatched action to resolve. Note that handleLogin won't, and can't see any updated isLoggedIn state value from Redux while it has a current value closed over in scope from the time it was called.
const handleLogin = async () => {
const userCredentials = { email, password };
const authSuccess = await userLogin(userCredentials);
if (authSuccess) {
console.log('I'm here');
} else {
console.log('wrong credentials');
}
};
use async await or then catch in handleLogin function and also do not forgot to add return in userLogin and sub functions
`const handleLogin = async () => {
await userLogin(userCredentials);
if(isLoggedIn) {
console.log('here');
}
}`
or use then
`userLogin(userCredentials).then(() => { if(isLoggedIn){
console.log('here');
}});`

How save the user's id in Redux state from Firebase?

I try to store the id of the user from Firebase but it does not work. If Somebody has some advice pls tell me or recommend a better solution.
type here
So Guys I have this slice:
`
import { Toast } from "#chakra-ui/react";
import { async } from "#firebase/util";
import { createAsyncThunk, createSlice } from "#reduxjs/toolkit";
import {
getAuth,
createUserWithEmailAndPassword,
updateProfile,
signInWithEmailAndPassword,
onAuthStateChanged,
} from "firebase/auth";
import { setDoc, doc, serverTimestamp } from "firebase/firestore";
import { useSelector } from "react-redux";
import { db, auth } from "../firestore/firebase";
export const signUpWithEmail = createAsyncThunk(
"auth/signUpWithEmail",
async ({ firstName, lastName, email, password }) => {
const userCredential = await createUserWithEmailAndPassword(
auth,
email,
password
);
const user = userCredential.user;
updateProfile(auth.currentUser, { displayName: firstName });
const formData = { firstName, lastName, email };
formData.timestamp = serverTimestamp();
await setDoc(doc(db, "users", user.uid), formData);
}
);
export const signInwithEmail = createAsyncThunk(
"auth/signinWithEmail",
async ({ email, password }) => {
const userCredential = await signInWithEmailAndPassword(
auth,
email,
password
);
}
);
export const getUserId = createAsyncThunk("auth/getId", async () => {
onAuthStateChanged(auth, (user) => {
if (user) {
const uid = user.uid;
return uid;
}
});
});
const initialState = {
userId: null,
isloggedIn: false,
status: null,
};
export const authSlice = createSlice({
name: "auth",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(signUpWithEmail.fulfilled, (state, action) => {
state.status = "succsess";
})
.addCase(signUpWithEmail.pending, (state) => {
state.status = "loading";
})
.addCase(signUpWithEmail.rejected, (state) => {
state.status = "error";
})
.addCase(signInwithEmail.fulfilled, (state) => {
state.status = "succsess";
state.isloggedIn = true;
})
.addCase(signInwithEmail.rejected, (state) => {
state.status = "error";
})
.addCase(signInwithEmail.pending, (state) => {
state.status = "loading";
})
.addCase(getUserId.fulfilled, (state, action) => {
state.userId = action.payload;
if (action.payload) {
state.isloggedIn = true;
}
});
},
});`
export default authSlice.reducer;
And in the index.js i call the function.
`store.dispatch(getUserId());`
I am expecting that I always can accses to the userId with the useSelector.
thx for a lot.

react toastify with redux from axios API

i am trying to send the error messages that sent from my server ( express ) to axios and the error message displays in toastify component but the error message doesn't show up here is the login axios function with the toastify how can i display toastify message inside my page from redux ?
here is my code :
// redux controller
const login = async (username, password) => {
await axios.post("/login",{username,password,},
{ withCredentials: true });};
// reducer page
export function generateError(prop) {
return function (dispatch) {
dispatch({
type: "USER_FAIL"
});
toast.error(prop);
};
}
export function generateSuccess(prop) {
return function (dispatch) {
dispatch({
type: "USER_SUCCESS"
});
toast.success(prop);
};
}
export const login = createAsyncThunk(
"/login",
async ({ username, password }) => {
try {
const data = await authService.login(username, password);
if (data) {
if (data.errors) {
const { username, password } = data.errors;
if (username) generateError(username)
else if (password) generateError(password);
} else {
generateSuccess(data.success);
}
}
return { user: data };
} catch (error) {
console.log(error);
}
}
);
// login page
const handleSubmit = (e) => {
e.preventDefault();
dispatch(login({ username, password }));
}
i am using react-tostify and #redux-toolkit but the message doesn't display inside my page
i fixed it and here is my code :
// auth.js ( redux page )
export const login = createAsyncThunk(
"/login",
async ({ username, password }) => {
try {
const {data} = await axios.post(
"/login",
{
username,
password,
},
{ withCredentials: true }
);
return { user: data };
} catch (error) {
console.log(error);
}
});
const initialState = user
? { isLoggedIn: true, user }
: { isLoggedIn: false, user: null };
const authSlice = createSlice({
name: "auth",
initialState,
extraReducers: {
[login.fulfilled]: (state, action) => {
state.isLoggedIn = true;
state.user = action.payload.user;
},
[login.rejected]: (state, action) => {
state.isLoggedIn = false;
state.user = null;
},
[logout.fulfilled]: (state, action) => {
state.isLoggedIn = false;
state.user = null;
},
}})
const { reducer } = authSlice; export default reducer;
Login Page :
const { isLoggedIn } = useSelector((state) => state.auth);
const dispatch = useDispatch();
const handleSubmit = (e) => {
e.preventDefault();
dispatch(login({ username, password })).then(data => {
console.log(data)
if (data.payload.user) {
if (data.payload.user.errors) {
const { username, password } = data.payload.user.errors;
if (username) generateError(username)
else if (password) generateError(password);
} else {
generateSuccess(data.success);
navigate("/dashboard");
}
}
})
}
i realized when i back the data it has an object name payload i used it to get the error messages from express and then i put the message in toastify function gettingError and here it is
const generateError = error => {
toast.error(error, {
position: "bottom-right",
})
}
Hai I'm also looking for the same problem while searching I found a solution at with this : react-toastify-with-redux
my Code : authAction.js
import 'react-toastify/dist/ReactToastify.min.css';
import { toast} from 'react-toastify';
export const registerUser = (userData) => dispatch =>{
axios.post('user/register',userData)
.then(res=>toast.success('Your Account Created Successfully ๐Ÿ‘'))
.then(res=> window.location = '/authentication/sign-in')
.catch(err=>dispatch(
{
type: GET_ERRORS,
payload: err.response.data
}
),toast.error("Error ๐Ÿ˜ฃ"))
// .catch((err)=> {return })
};
On your signUp page just add
<ToastContainer />
That's all ...
This answer is probably late. But I came across this problem and decided to do it my way. I know there is toast. promise to handle promises and I don't want to call dispatch.then every time. So I can up with passing dispatch to my action wrapper. Here is my code.
// utils.ts
type ArgumentTypes<F extends CallableFunction> = F extends (
...args: infer A
) => any
? A[0]
: never;
export const withToast = <T = AnyAction | typeof createAsyncThunk>(
action: T,
{ pending, error, success }: ToastPromiseParams<T>
) => {
return (
dispatch: ReturnType<typeof useAppDispatch>,
actionParams?: ArgumentTypes<T & CallableFunction> | void
) => {
const promise = dispatch(
(action as CallableFunction)(actionParams as any)
).unwrap();
toast.promise(promise, {
pending,
error,
success,
});
};
};
// actions.ts
export const login = createAsyncThunk(
"user/login",
async (payload: {
email: string;
password: string;
}): Promise<Partial<LoginAPIResponse>> => {
const { data } = await axios.post(`${API}/${LOGIN_EP}/`, payload);
return data;
}
);
export const loginWithToast = withToast(login, {
pending: "Logging in...",
error: {
render: (error: any) => {
return error?.password || error?.email
? "Invalid email or password"
: "Something went wrong";
},
},
success: "Logged in successfully",
});
// usage in component
const dispatch = useAppDispatch();
loginWithToast(dispatch, {
email: values.email.value,
password: values.password.value,
});
First createAsyncThunk:
import { coreAxios } from "utilities/axios"; // Own customized axios
import { createAsyncThunk } from "#reduxjs/toolkit";
const BASE_URL = process.env.REACT_APP_MAIN_URL
export const GetProducts = createAsyncThunk(
"inventory/GetProducts",
async () => {
const {data} = await coreAxios.get(`${BASE_URL}/api/product/list/`);
return data
}
);
Second createSlice:
import { createSlice } from "#reduxjs/toolkit";
import { GetProducts } from "services/inventory/product.service";
import { toast } from 'react-toastify';
export const productSlice = createSlice({
name: "products",
initialState: {
productsList: [],
productsLoading: false,
productsError: null,
},
extraReducers:
(builder) => {
builder.addCase(GetProducts.pending, (state) => {
toast.loading('Promise is pending...')
state.productsLoading = true
});
builder.addCase(GetProducts.fulfilled, (state, action) => {
toast.dismiss();
toast.success('Promise resolved ๐Ÿ‘Œ');
state.productsList = action.payload
state.productsLoading = false
state.productsError = null
});
builder.addCase(GetProducts.rejected, (state, action) => {
toast.dismiss();
toast.error('Promise rejected ๐Ÿคฏ ๐Ÿ˜ฃ')
state.productsLoading = false
state.productsError = action.error?.message
});
},
});
export default productSlice.reducer;
Third page:
import { ToastContainer } from 'react-toastify';
import { useSelector, useDispatch } from "react-redux";
import { GetProducts } from 'services/inventory/product.service';
const Product = () => {
const { productsList, productsLoading, productsError } = useSelector((state) => state.products);
const dispatch = useDispatch();
useEffect(() => {
dispatch(GetProducts());
}, []);
return (
<div className="grid crud-demo">
<h1>Hello Alim</h1>
<ToastContainer />
</div>
);
}

Why doesn't useEffect hook work on page refresh?

I'm working on a react project. I have my own API to fetch information. I'm using the useEffect hook to fetch profile information from API. My problem is when page mounts for the first time i can fetch the data with no problem but if i refresh the page it doesn't work at all. I know i have to give a second parameter to useEffect. I tried to put profile as the second argument even dispatched the getCurrentProfile function but when i do that it constantly fires off fetch request. I would be glad if anyone can help me with that. Thanks.
Here is my Profile component:
export const Profile = () => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(getCurrentProfile());
}, [])
const profileReducer = useSelector((state) => state.profile);
const authReducer = useSelector((state) => state.auth);
const { profile, error, loading } = profileReducer;
const { user } = authReducer;
console.log("loading", loading)
console.log("profile", profile)
return loading && profile === null ? (
<div >
<Spinner />
</div>
) :
Here is my Profile action:
export const getCurrentProfile = () => async dispatch => {
try {
const res = await axios.get("/api/profile/me");
console.log(res);
dispatch({
type: "GET_PROFILE",
payload: res.data.data
})
} catch (err) {
dispatch({
type: "PROFILE_ERROR",
payload: { msg: err.response.statusText, status: err.response.status }
})
}
}
Here is my profile reducer:
export default (state = initialState, action) => {
const { type, payload } = action;
switch (type) {
case "GET_PROFILE":
return {
...state,
profile: payload,
loading: false
}
case "PROFILE_ERROR":
return {
...state,
error: payload,
profile: null
}
case "CLEAR_PROFILE":
return {
...state,
profile: null,
loading: false
}
default:
return state;
}
}
You might want to try adding conditional logic within the useEffect so you only trigger the dispatch if you don't already have a profile.
import "./styles.css";
import { useDispatch, useSelector } from "react-redux";
import { useEffect, useCallback } from "react";
import { getCurrentProfile } from "./action";
export const Profile = () => {
const dispatch = useDispatch();
const profileReducer = useSelector((state) => state.profile);
const authReducer = useSelector((state) => state.auth);
const { profile, error, loading } = profileReducer;
// read more about this here: https://stackoverflow.com/questions/58624200/react-hook-useeffect-has-a-missing-dependency-dispatch
const stableDispatch = useCallback(dispatch, []);
useEffect(() => {
if (!profile) {
stableDispatch(getCurrentProfile());
}
}, [profile, stableDispatch]);
const { user } = authReducer;
console.log("loading", loading);
console.log("profile", profile);
return loading && profile === null ? <div>Spinner</div> : "Actual Profile";
};
export default Profile;
Also, it doesn't seem like you're currently doing anything with the loading piece of stateโ€“at least from what you've shared here. You might want to dispatch an action indicating that you're loading before you start the fetch and then it will be set to false when you get the response.
Check out this codesandbox for reference: https://codesandbox.io/s/focused-kilby-gd2nr?file=/src/App.js
Reducers:
const initialState = {
profile: null,
loading: false
};
export const profile = (state = initialState, action) => {
const { type, payload } = action;
switch (type) {
case "LOADING_PROFILE":
return {
...state,
loading: true
};
case "GET_PROFILE":
return {
...state,
profile: payload,
loading: false
};
case "PROFILE_ERROR":
return {
...state,
error: payload,
profile: null
};
case "CLEAR_PROFILE":
return {
...state,
profile: null,
loading: false
};
default:
return state;
}
};
export const auth = (state = {}, action) => {
return state;
};
Action Creator:
import axios from "axios";
export const getCurrentProfile = () => async (dispatch) => {
try {
dispatch({ type: "LOADING_PROFILE" });
const res = await axios.get("https://jsonplaceholder.typicode.com/users/1");
console.log(res);
dispatch({
type: "GET_PROFILE",
payload: res.data.data
});
} catch (err) {
dispatch({
type: "PROFILE_ERROR",
payload: { msg: err.response.statusText, status: err.response.status }
});
}
};
index.js
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore, combineReducers, applyMiddleware } from "redux";
import { profile, auth } from "./reducers";
import App from "./App";
import thunk from "redux-thunk";
const store = createStore(
combineReducers({
profile,
auth
}),
applyMiddleware(thunk)
);
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
rootElement
);
Well i solved it by dispatching 'getCurrentProfile' not 'getCurrentProfile()' turns out using it like a function causes continuously firing off.
const profileReducer = useSelector((state) => state.profile);
const authReducer = useSelector((state) => state.auth);
const { profile, error, loading } = profileReducer;
const dispatch = useDispatch();
useEffect(() => {
if (!profile) {
console.log("It worked")
dispatch(getCurrentProfile());
}
}, [dispatch(getCurrentProfile)])

React native Redux useDispatch not working

I try to create a Redux and I have a problem when I try to do dispatch is not working.
Action file, userActions.js:
export const setId = () => {
console.log("Enter to set id func");
return {
type: 'SET_ID'
}
}
Reducer file, userReducer.js:
const INITIAL_STATE = {
id: "",
email: "",
name: "",
};
const userReducer = (state = INITIAL_STATE, action) => {
console.log('Enter to userReducer');
switch (action.type) {
case "SET_ID": {
// console.log(action.payload);
}
default: {
return state;
}
}
}
export default userReducer;
combineReducers file:
import userReducer from "./userReducer";
import { combineReducers } from "redux";
const allReducers = combineReducers({
userReducer: userReducer
})
export default allReducers;
App.js file:
import React from 'react';
import Routes from "./Routes";
import { createStore } from "redux";
import allReducer from "./app/reducers";
import { Provider } from "react-redux";
const store = createStore(
allReducer
);
const App = () => {
return (
<Provider store={store}>
<Routes />
</Provider>
);
};
export default App;
In login screen file, I have button when I click on him call to dispatch to "setId" action.
Here some of my code from Login.js:
import { useDispatch } from 'react-redux';
import { setId } from '../actions/userActions';
handleLoginResult = (error, user) => {
console.log('Enter to handleLoginResult');
if (error !== "") {
this.setState({ generalError: error });
} else {
const dispatch = useDispatch();
console.log('uid: ', user.user.uid);
dispatch(setId());
alert("Login!");
}
}
What is the problem and why is not enter to setId action?
You can try with like this
const userReducer = (state = INITIAL_STATE, action) =>dispatch =>{
console.log('Enter to userReducer');
switch (action.type) {
case "SET_ID": {
// console.log(action.payload);
}
default: {
return state;
}
}
}
I didn't quite understand your question, but I'll give you an example of an action of mine
export const register_user = ({ name, email, password, password_confirmation }) => {
return dispatch => {
dispatch(
{
type: CREATE_USER
}
)
let url = "/users"
Axios.post(`${SERVER}${url}`, {
"user": {
"name": name,
"email": email,
"password": password,
"password_confirmation": password_confirmation
}
})
.then(() => {
Alert.alert('Registrado com sucesso!')
registerUserSuccess(dispatch)
})
.catch((err) => {
registerUserError(err, dispatch)
})
}
}
const registerUserSuccess = (dispatch) => {
dispatch(
{
type: CREATE_USER_SUCCESS
}
)
this.props.navigation.navigate('Login')
}
const registerUserError = (err, dispatch) => {
dispatch(
{
type: CREATE_USER_ERROR
}
)
Alert.alert('Algo deu errado, verifique suas credenciais.')
}
The type is exported from my reducer.
And the register_user constant is imported and used on my register screen.
Hooks cannot be used inside a function. They need to declared directly inside the functional component.
Also useDispatch hook cannot be used inside a class component, you must use connect for a class component.
Assuming you have a class component, judging by how you use this.setState, you would write your code like
class Login extends React.Component {
...
handleLoginResult = (error, user) => {
console.log('Enter to handleLoginResult');
if (error !== "") {
this.setState({ generalError: error });
} else {
const dispatch = this.props;
console.log('uid: ', user.user.uid);
dispatch(setId());
alert("Login!");
}
}
...
}
export default connect()(Login)
If however you were to write login as a functional component, you would write it like
const Login = (props) => {
const dispatch = useDispatch();
const [state, setState] = useState({});
...
const handleLoginResult = (error, user) => {
console.log('Enter to handleLoginResult');
if (error !== "") {
setState({ generalError: error });
} else {
console.log('uid: ', user.user.uid);
dispatch(setId());
}
}
...
}

Resources