React Hooks + Redux+TypeScript

Yasin DALKILIÇ
4 min readNov 20, 2020

--

React kullanırken state managment için her ne kadar contextler üzerinden statelerimizi yönetebiliyor olsak da hali hazırda olan çeşitli state managment kütüphaneleri (redux,mobx) gibi hala kullanılmaktadır. Bu yazımızda react hooklarla beraber redux’ı nası kullanacağımızı göreceğiz bunu yaparken de typescript’den yararlanıyor olacağız. Örneğimizde basitçe bir todo modulü barındırıyor olacağız. Lafı uzatmadan başlayalım.

Kurulumlar

1-)React projesi oluşturma

npx create-react-app my-app --template typescript

2-)redux , react-redux , axios , redux-thunk kurulumu

npm install --save react-redux @types/react-redux
npm install --save axios
npm install --save redux-thunk
npm install --save redux

Redux dosya ve klasör yapısının kurulması

src/store ve src/store/todo klasörlerini oluşturalım.

Todo Modulü:

src/store/todo/todoModel.ts dosyamızı

export interface todoModel{userId:number,id:numbertitle:stringcompleted:boolean}

src/store/todo/state.ts dosyamızı oluşturalım.

export interface todoState {error: stringloading: booleantodos: Array<todoModel>}export const initialState: todoState = {loading: false,todos: [],error: ''}

todo modülümüz için ilgili state değerimizi ve interfacemizi oluşturduk. Statemizi açıklayacak olursak;

error: Oluşan hatalar için tutacağımız değer

loading: Veri çekerken verilerin yükleniyor olduğunu göstermek için kullanacağımız değer

todos: İçerisinde verilerimizi barındıracağımız değer.

src/store/todo/const.ts

reducerlar da kullanacağımız action typelarımızı oluşturalım.

export  const FETCH_TODO_REQUEST="FETCH_TODO_REQUEST"
export const FETCH_TODO_SUCCESS="FETCH_TODO_SUCCESS"
export const FETCH_TODO_ERROR="FETCH_TODO_ERROR"
export const DELETE_TODO_SUCCESS="DELETE_TODO_SUCCESS"
export const DELETE_TODO_ERROR="DELETE_TODO_ERROR"

src/store/todo/actionsModels.ts

import {DELETE_TODO_ERROR,DELETE_TODO_REQUEST,DELETE_TODO_SUCCESS,FETCH_TODO_ERROR,FETCH_TODO_REQUEST,FETCH_TODO_SUCCESS
import { todoModel } from "./todoModel"} from "./consts";
export interface todosFetch {type: typeof FETCH_TODO_REQUEST}export interface todoSuccess {type: typeof FETCH_TODO_SUCCESSpayload: Array<todoModel>}export interface todoError {type: typeof FETCH_TODO_ERRORerror: any}export interface deleteTodoRequest {type: typeof DELETE_TODO_REQUEST}export interface deleteTodoSuccess {type: typeof DELETE_TODO_SUCCESSpayload: any}export interface deleteTodoError {type: typeof DELETE_TODO_ERRORerror: any}export type todoActions =todosFetch| todoSuccess| todoError| deleteTodoRequest| deleteTodoError| deleteTodoSuccess;

actionlarımızla ilgili interfacelerimizi oluşturduğumuza göre şimdi actionslarımızı yazmaya başlayabiliriz.

src/store/todo/actions.ts

import {DELETE_TODO_ERROR,DELETE_TODO_SUCCESS,FETCH_TODO_ERROR,FETCH_TODO_REQUEST,FETCH_TODO_SUCCESS} from "./consts";import axios from 'axios'import {deleteTodoError,deleteTodoSuccess, todoError,todoSuccess,todosFetch} from './actionsModels'import { todoModel } from "./todoModel";export const deleteTodoErrorRequest = (error: any): deleteTodoError => ({error,type: DELETE_TODO_ERROR});export const delTodoSuccess = (payload: any): deleteTodoSuccess => ({type: DELETE_TODO_SUCCESS,payload})export const todoFetch = (): todosFetch => ({type: FETCH_TODO_REQUEST,});export const todoFetchSuccess = (payload: Array<todoModel>): todoSuccess => ({type: FETCH_TODO_SUCCESS,payload});export const todoFetchError = (error: any): todoError => ({type: FETCH_TODO_ERROR,error});export const deleteTodos = (item: todoModel) => {return async (dispatch: any) => {dispatch(delTodoSuccess(item))}}export const fetchTodos = () => {return async (dispatch: any) => {dispatch(todoFetch());try {const response = await axios.get('https://jsonplaceholder.typicode.com/todos')dispatch(todoFetchSuccess(response.data))} catch (error) {dispatch(todoFetchError(error))}}}

ilgili actionslarımızın tiplerini belirterek oluşturduk, yalnızca fetch işlemi için backend bağlantısı kullanıyorum.

src/store/todo/reducers.ts

import {initialState} from "./state";import {todoActions} from "./actionsModels";import {DELETE_TODO_ERROR,DELETE_TODO_SUCCESS,FETCH_TODO_ERROR,FETCH_TODO_REQUEST,FETCH_TODO_SUCCESS} from "./consts";const todoReducers = (state = initialState, action: todoActions) => {switch (action.type) {case FETCH_TODO_REQUEST:return {...state,loading: true}case FETCH_TODO_ERROR:return {...state,todos: [],error: action.error}case FETCH_TODO_SUCCESS : {return {...state,todos: action.payload,loading: false}}case DELETE_TODO_ERROR: {return {...state,error: action.error}}case DELETE_TODO_SUCCESS: {let newTodos = [...state.todos]newTodos = newTodos.filter((item) => item.id !== action.payload.id)return {...state,loading: false,todos: newTodos}}default:return state}};export default todoReducers

todo modülü için gerekli reducerı da oluşturduktan sonra bu modül ile işimizi tamamlayıp bir sonraki adıma geçiyoruz.

src/store/todo/rootState.ts

import {todoState} from "./todos/state";export interface rootState {todo: todoState}

kullanacağımız modüle ait interface oluşturduktan sonra sırada rootReducerımızı oluşturalım.

src/store/todo/rootReducers.ts

import {combineReducers} from "redux";import todoReducers from "./todos/reducers";const rootReducer = combineReducers({todo: todoReducers})export default rootReducer

rootReducersımızda tek bir modul olmasına rağmen ilerisini ve farklı modüller olacağını düşünerek combineReducers fonskiyonunu kullanıyorum ardından src/store/todo/store.ts

import {createStore, applyMiddleware} from 'redux'import rootReducer from "./rootReducers";import thunk from "redux-thunk";const store = createStore(rootReducer, applyMiddleware(thunk))export default store;

store dosyamızda ilgili tanımlamaları ve middleware gerçekleştirip en nihayetinde src/index.tsx dosyamızda Provider ile bütün uygulamayı kaplayıp ilgili store dahil ediyoruz.

import React from 'react';import ReactDOM from 'react-dom';import './index.css';import App from './App';import reportWebVitals from './reportWebVitals';import {Provider} from 'react-redux'import store from "./store/store";ReactDOM.render(<React.StrictMode><Provider store={store}><App/></Provider></React.StrictMode>,document.getElementById('root'));

Redux yapımızı kullanalım

src/app.tsx dosyamızda

import {useDispatch, useSelector} from "react-redux";import {fetchTodos} from "./store/todos";import {rootState} from "./store/rootState";import React, {useLayoutEffect}function App() {const state = useSelector<rootState, rootState['todo']>(state => state.todo)const dispatch = useDispatch();useLayoutEffect(() => {getTodo();}, [])const getTodo = () => {dispatch(fetchTodos())}
return (
<div className="App"><pre>{JSON.stringify(state, null,2)}</pre></header></div>);
}

useSelector hookunu kullanarak state içersinde yer alan todo modülünü kullanacağımı belirttim ve component ilk render olduğunda fetchTodos’u dispatch ettim.

Herkese İyi Çalışmalar Dilerim. :)

--

--

Yasin DALKILIÇ
Yasin DALKILIÇ

Written by Yasin DALKILIÇ

Hi, My name is Yasin I am a Software Developer, I love so much researching and development 😊 Here is my youtube channel @webciyasin

No responses yet