Redux Temelleri
⚛️

Redux Temelleri

references
growth status
seedling
Created
Oct 4, 2022 05:58 AM
Tags
redux
💡
Bu kısımda Redux nedir ve neden kullanmak isteriz, redux ile bir geliştirme yapmak için nelere ihtiyacımız var bunu konuşacağız.
 
useEffect() ile ilgili bir sorun Şu anda yaptığımız şekilde useEffect'i kullanırken bir sorunla karşılaşıyoruz: Uygulamamız başladığında yürütülecek.
neden bu bir sorundur?
Bu bir sorun çünkü bu, ilk (yani boş) sepeti arka ucumuza gönderecek ve orada depolanan verilerin üzerine yazacaktır.
Bunu sonraki derslerde çözeceğiz, sadece burada belirtmek istedim!
Reducerlarımız pure, side-effectleri olmayan, ve senkron fonksiyonlar olmalı.
İnput(old state + action ) ⇒ Output (New State)
Reducer’ı kullanmak için verdiğiniz reducer fonksiyonu react hook’udur.
aynı inputlar için her zaman aynı outputu vermelidir.
//TODO: buraya jest testi örneği gelecek.
Redux ile bir ilgisi yoktur. Ama genel reducer konsepti , fonksyionun pure ve pure ve side effects synchronous function that takes input and produces some output, without any side effects that happen along the way without any async code that blocks it. Böyle olmayan hiç bir kod reducer fonksiyonunun bir parçası olmamalı.
Bu da bizi önemli bir noktaya getiriyor. O zaman redux ile çalışırken bir bir http requesti içeren bir aksiyonu dispatch edersek ne olacak. O zaman bu side effect ya da async kodunu nereye eklemeliyiz?
Bu side effectleri componente koyabiliriz(useEffect gibi) o zaman redux side effect hakkında hiç bir şeyi bilmez.
Ya da action creator fonksiyonları yazarız.
redux'un aslında, bu action creatorların bir parçası olarak, reducer işlevini değiştirmeden yan etkileri gerçekleştirmemize ve asenkron görevleri çalıştırmamıza izin veren bir çözümü var, çünkü bu işlev yan etkiden uzak kalmalıdır.
 
 
npm i react-redux
 
Bunu uygulamamıza bağlamak için ;
src klasörünün altına store klasörü açıyoruz. (common convension)
kodları ayrı tutmak her zaman için sürdürülebilir ve düzenlemesi kolay bir altyapı sunar.
Öncelikle slicelara öznel isimler veriyoruz. Sonra initial durumlarını veriyoruz. Ve reducer keyimiz var bu da bize tüm reducerlarımızı mapliyor. Tüm farklı durumlar ve farklı actionları temsil eden yöntemlerin bir haritasıdır.
Burda reducer’ı yazarken mutating code yazabiliriz. Çünkü burda Redux Toolkit bunu aslında mutate etmememizi sağlıyor. Toolkit bu kodu alıp başka bir 3rd party immer kütüphasi ile immutable koda çeviriyor. .
// store/index.js import {configureStore} from '@reduxjs/toolkit'; import uiSlice form './ui-slice'; configureStore({ reducer: {ui: uiSlice.reducer} }) export default store;
// store/ui-slice.js import { createSlice } from "@reduxjs/toolkit"; const uiSlice = createSlice({ name: "ui", initialState: { cartIsVisible: false }, reducers: { toggle(state) { state.cartIsVisible = !state.cartIsVisible; }, }, }); export const uiActions = uiSlice.actions; export default uiSlice;
// store/chart-slice.js
// index.js import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App"; import store from "./store/index"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <Provider store={store}> <App /> </Provider> );
// components/Cart/CartButton.js import { useDispatch } from "react-redux"; import { uiActions } from "../../store/ui-slice"; import classes from "./CartButton.module.css"; const CartButton = (props) => { const dispatch = useDispatch(); const toggleCartHandler = () => { dispatch(uiActions.toggle()); }; return ( <button className={classes.button} onClick={toggleCartHandler}> <span>My Cart</span> <span className={classes.badge}>1</span> </button> ); }; export default CartButton;
Burada action olarak çağırdığımız otomatik üretilen actionlar aslında action creator methodlarıdır.
Bizim bu methodları execute etmemiz gerekir. Execute ettiğimizde bize action objesi dönerler.
notion image
UI slice’daki state değişimine göre komponentimizde koşullu bir render gerçekleştirmek istiyoruz.
Bunun için de react redux’tan aldığımız başka bir hook’u kullanıyor olacağız.
useSelector.
// App.js import { useSelector } from "react-redux"; import Cart from "./components/Cart/Cart"; import Layout from "./components/Layout/Layout"; import Products from "./components/Shop/Products"; function App() { const showCart = useSelector((state) => state.ui.cartIsVisible); return ( <Layout> {showCart && <Cart />} <Products /> </Layout> ); } export default App;
"redux state" alan bir fonksiyon geçmemiz gerekiyor otomatik olarak çünkü bu fonksiyon useSelector a ilettiğimiz yürütülecek React Redux tarafından.
Yani şu anki state ‘i alıp bu komponentin kullacağı datayı return ediyor.
 
//TODO: code
 
Şimdi ise Reducerların pure, side effect free ve syncrounous olması gerektiğini göz önünde bulundurarak backende istekler atacağız. Sepetin durumu güncellendiğinde bunu backendde güncelleyip yenilendiğinde bu bilgi kalsın istiyorum. böyle bir kod reducra gitmemeli.
 
1- Eğer component içinde bunları kullanmak istersek;
Selector logicini componente taşımak ve değişen datayı kullanıp dispatch çağırmak gerekir. Bu durumda senkronluğu sağlayabiliriz. Ancak componentimiz fat bit componente dönüşür.
notion image
 
//App.js import { useEffect } from "react"; import { useSelector } from "react-redux"; import Cart from "./components/Cart/Cart"; import Layout from "./components/Layout/Layout"; import Products from "./components/Shop/Products"; function App() { const showCart = useSelector((state) => state.ui.cartIsVisible); const cart = useSelector((state) => state.cart); useEffect(() => { fetch("somefirebaselink.com/cart.json", { method: "PUT", body: JSON.stringify(cart), }); }, [cart]); return ( <Layout> {showCart && <Cart />} <Products /> </Layout> ); } export default App;
useEffect ‘i kullanarak selectordaki data güncellenir güncellenmz backendi bundan haberdar etmiş olduk.
useEffect() ile ilgili bir sorun Şu anda yaptığımız şekilde useEffect'i kullanırken bir sorunla karşılaşıyoruz: Uygulamamız başladığında yürütülecek.
neden bu bir sorundur?
Bu bir sorun çünkü bu, ilk (yani boş) sepeti arka ucumuza gönderecek ve orada depolanan verilerin üzerine yazacaktır.
Bunu sonraki derslerde çözeceğiz, sadece burada belirtmek istedim!
//App.js import { Fragment, useEffect } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import Cart from './components/Cart/Cart'; import Layout from './components/Layout/Layout'; import Products from './components/Shop/Products'; import { uiActions } from './store/ui-slice'; import Notification from './components/UI/Notification'; let isInitial = true; function App() { const dispatch = useDispatch(); const showCart = useSelector((state) => state.ui.cartIsVisible); const cart = useSelector((state) => state.cart); const notification = useSelector((state) => state.ui.notification); useEffect(() => { const sendCartData = async () => { dispatch( uiActions.showNotification({ status: 'pending', title: 'Sending...', message: 'Sending cart data!', }) ); const response = await fetch( 'https://react-http-6b4a6.firebaseio.com/cart.json', { method: 'PUT', body: JSON.stringify(cart), } ); if (!response.ok) { throw new Error('Sending cart data failed.'); } dispatch( uiActions.showNotification({ status: 'success', title: 'Success!', message: 'Sent cart data successfully!', }) ); }; if (isInitial) { isInitial = false; return; } sendCartData().catch((error) => { dispatch( uiActions.showNotification({ status: 'error', title: 'Error!', message: 'Sending cart data failed!', }) ); }); }, [cart, dispatch]); return ( <Fragment> {notification && ( <Notification status={notification.status} title={notification.title} message={notification.message} /> )} <Layout> {showCart && <Cart />} <Products /> </Layout> </Fragment> ); } export default App;
Action Creator Thunk
Thunk nedir ?
Bir thunk basitçe bir actionı başka bir action bitene kadar erteleyen bir fonksiyondur,
 
Action creator fonksiyonu aksiyonu değiş eninde sonunda fonksiyon döndürecek başka bir fonksiyonu döndürür.
notion image
 
notion image
notion image
notion image
notion image
and it will execute this function for us.
And therefore all our other actions will be dispatched,
and the HTTP request will be sent.
notion image