Redux Redüktörler Nasıl Çalışır?
Yayınlanan: 2022-03-10state
yönetimi için bir uygulama geliştirirken herhangi bir noktada Redux kullandıysanız, kesinlikle redüktörlerle karşılaşmışsınızdır. Bu eğitim, redüktör kavramını ve özellikle Redux'ta nasıl çalıştıklarını açıklayacaktır.Bu eğitimde, redüktör kavramını ve özellikle React uygulamalarında nasıl çalıştıklarını öğreneceğiz. Redux'u anlamak ve daha iyi kullanmak için, redüktörlerin sağlam bir şekilde anlaşılması önemlidir. Düşürücüler, bir eylem kullanarak bir uygulamanın durumunu güncellemek için bir yol sağlar. Redux kütüphanesinin ayrılmaz bir parçasıdır.
Bu eğitim, Redux Redüktörler hakkında daha fazla bilgi edinmek isteyen geliştiriciler içindir. React ve Redux'u anlamak faydalı olacaktır. Eğitimin sonunda, Redux'ta Redüktörlerin oynadığı rolü daha iyi anlayacaksınız. Redüktörleri ve bir uygulamadaki durumu nasıl etkilediğini daha iyi anlamak için kod demoları ve bir uygulama yazacağız.
Redüktör Nedir?
Bir Redüktör, bir uygulamanın ve eylemin durumunu argüman olarak alan ve yeni bir durum döndüren saf bir işlevdir. Örneğin, bir kimlik doğrulama azaltıcı, bir uygulamanın ilk durumunu boş bir nesne ve bir kullanıcının oturum açtığını ve oturum açmış bir kullanıcıyla yeni bir uygulama durumu döndürdüğünü bildiren bir eylem biçiminde alabilir.
Saf işlevler, herhangi bir yan etkisi olmayan ve aynı argümanlar iletilirse aynı sonuçları döndüren işlevlerdir.
Aşağıda bir saf fonksiyon örneği verilmiştir:
const add = (x, y) => x + y; add(2, 5);
Yukarıdaki örnek, girdilere dayalı bir değer döndürür, 2
ve 5
geçerseniz, her zaman 7
alırsınız, aynı girdi olduğu sürece, aldığınız çıktıyı başka hiçbir şey etkilemez, bu saf bir işlev örneğidir.
Aşağıda, bir durum ve eylem alan bir indirgeyici işlevi örneği verilmiştir.
const initialState = {}; const cartReducer = (state = initialState, action) => { // Do something here }
Bir redüktörün aldığı iki parametreyi, state
ve action
tanımlayalım.
Belirtmek, bildirmek
Durum , bileşenlerinizin birlikte çalıştığı verilerdir - bir bileşenin gerektirdiği verileri tutar ve bir bileşenin ne oluşturduğunu belirler. Bir state
nesnesi değiştiğinde, bileşen yeniden oluşturulur. Bir uygulama durumu Redux tarafından yönetiliyorsa, durum değişikliklerinin gerçekleştiği yer redüktördür.
Aksiyon
Eylem, bilgi yükünü içeren bir nesnedir. Redux mağazasının güncellenmesi için tek bilgi kaynağıdır. Redüktörler, action.type
değerine göre depoyu günceller. Burada action.type
olarak ADD_TO_CART
.
Resmi Redux belgelerine göre, bir Redux uygulamasında değişiklikleri tetikleyen tek şey eylemlerdir, bir uygulama mağazasındaki değişikliklerin yükünü içerirler. Eylemler, Redux'a gerçekleştirilecek eylem türünü söyleyen JavaScript nesneleridir, genellikle aşağıdaki gibi işlevler olarak tanımlanırlar:
const action = { type: 'ADD_TO_CART', payload: { product: 'margarine', quantity: 4 } }
Yukarıdaki kod, bir kullanıcının ne gönderdiğini içeren tipik bir payload
değeridir ve uygulamanın durumunu güncellemek için kullanılacaktır. Yukarıdan da görebileceğiniz gibi, eylem nesnesi, bu belirli eylemin gerçekleştirilmesi için gerekli olacak eylem türünü ve bir yük nesnesini içerir.
Redüktörleri Kullanarak Durumu Güncelleme
Redüktörlerin nasıl çalıştığını göstermek için aşağıdaki sayı sayacına bakalım:
const increaseAction = { type: 'INCREASE', }; const decreaseAction = { type: 'DECREASE' }; const countReducer = (state = 0, action) => { switch(action.type){ case INCREASE: return state + 1; case DECREASE : return state -1; default: return state; } };
Yukarıdaki kodda, increaseAction
ve decreaseAction
, state
ne olarak güncellendiğini belirlemek için redüktörde kullanılan eylemlerdir. Daha sonra, bir action
ve değeri 0
olan bir başlangıç state
alan countReducer
adlı bir indirgeyici işlevimiz var. action.type
değeri INCREASE
ise, 1 artan yeni bir durum döndürürüz, aksi takdirde DECREASE
ise 1 azaltılan yeni bir durum döndürür. Bu koşullardan hiçbirinin kastedilmediği durumlarda, state
döndürürüz.
İndirgeyiciler Kullanarak Durumu Güncelleme: Yayılma Operatörü
Durum doğrudan değiştirilemez, durum oluşturmak veya güncellemek için, durumun değerini doğrudan değiştirmediğimizden emin olmak için JavaScript yayılma operatörünü kullanabiliriz, bunun yerine kendisine geçirilen bir durumu içeren yeni bir nesneyi döndürebiliriz ve kullanıcının yükü.
const contactAction = { type: 'GET_CONTACT', payload: ['0801234567', '0901234567'] }; const initialState = { contacts: [], contact: {}, }; export default function (state = initialState, action) { switch (action.type) { case GET_CONTACTS: return { ...state, contacts: action.payload, }; default: return state; }
Yukarıdaki kodda, durum değerini doğrudan değiştirmediğimizden emin olmak için bir yayılma operatörü kullanıyoruz, bu şekilde kendisine iletilen durum ve tarafından gönderilen yük ile dolu yeni bir nesne döndürebiliriz. kullanıcı. Bir yayılma operatörü kullanarak, tüm yeni öğeleri eklediğimizde durumun aynı kaldığından emin olabilir ve daha önce mevcutsa durumdaki kişiler alanını da değiştirebiliriz.
Redux Redüktörler İş Başında — Bir Demo
Redux Redüktörleri ve nasıl çalıştıklarını daha iyi anlamak için basit bir Film ayrıntıları bulma uygulaması uygulayacağız, kod ve çalışma sürümü burada Codesandbox'ta bulunabilir. Başlamak için terminalinize gidin ve aşağıdaki komutu kullanarak bir tepki uygulaması başlatın:
create-react-app movie-detail-finder
Projemiz başlatıldıktan sonra, uygulamamız için ihtiyaç duyacağımız paketleri kuralım.
npm i axios reactstrap react-redux redux redux-thunk
Paketler yüklendikten sonra, şu komutu kullanarak geliştirme sunucumuzu başlatalım:
npm start
Yukarıdaki komut, tarayıcımızda proje geliştirme sunucumuzu başlatmalıdır. Ardından, projemizi seçtiğimiz metin düzenleyicimizde açalım, proje src
klasörümüzün içindeki şu dosyaları silelim: App.css
, App.test.js
, serviceWorker.js
ve setupTests.js
. Ardından, App.js'mizde silinen dosyalara referans veren tüm kodları App.js
.
Bu proje için, uygulamamız için film bilgilerimizi, içeriğimizi ve resimlerimizi almak için Open Movie Database API kullanacağız, işte API'ye bir bağlantı, bunun için kullanmak için kayıt olmanız ve erişim anahtarlarını almanız gerekir. Uygulamamız bittiğinde, bileşenleri oluşturarak uygulamamıza devam edelim.
Uygulama Bileşenleri Oluşturma
Öncelikle proje dizinimizde src
klasörümüzün içinde component adında bir klasör oluşturalım ve bu klasörün içinde Movie
ve Searchbar
adında iki klasör oluşturalım, componentimiz aşağıdaki resimdeki gibi görünmelidir:
Film Bileşeni Oluşturma
API'mizden alacağımız film ayrıntılarının yapısını özetleyecek olan Movies
bileşenini oluşturalım. Bunu yapmak için, bileşenimizin Movies
klasörünün içinde yeni bir Movie.js
dosyası oluşturun, ardından API sonuçları için sınıf tabanlı bir bileşen oluşturun, bunu aşağıda yapalım.
import React, { Component } from 'react'; import { Card, CardImg, CardText, CardBody, ListGroup, ListGroupItem, Badge } from 'reactstrap'; import styles from './Movie.module.css'; class Movie extends Component{ render(){ if(this.props.movie){ return ( <div className={styles.Movie}> <h3 className="text-center my-4"> Movie Name: {this.props.movie.Title} </h3> <Card className="text-primary bg-dark"> <CardImg className={styles.Img} top src={this.props.movie.Poster} alt={this.props.movie.Title}/> <CardBody> <ListGroup className="bg-dark"> <ListGroupItem> <Badge color="primary">Actors:</Badge> {this.props.movie.Actors} </ListGroupItem> <ListGroupItem> <Badge color="primary">Genre:</Badge> {this.props.movie.Genre} </ListGroupItem> <ListGroupItem> <Badge color="primary">Year:</Badge> {this.props.movie.Year} </ListGroupItem> <ListGroupItem> <Badge color="primary">Writer(s):</Badge> {this.props.movie.Writer} </ListGroupItem> <ListGroupItem> <Badge color="primary">IMDB Rating:</Badge> {this.props.movie.imdbRating}/10 </ListGroupItem> </ListGroup> <CardText className="mt-3 text-white"> <Badge color="secondary">Plot:</Badge> {this.props.movie.Plot} </CardText> </CardBody> </Card> </div> ) } return null } } export default Movie;
Yukarıdaki kodda, reactstrap
paketindeki bileşenleri kullanarak buradaki belgelere göz atabilirsiniz. Film adı, Görüntü, tür, oyuncu, yıl, film yazarı, derecelendirme ve olay örgüsünü içeren bir Kart bileşeni oluşturduk. Bu bileşenden veri aktarmayı kolaylaştırmak için verileri diğer bileşenlere destek olacak şekilde oluşturduk. Ardından, Searchbar
bileşenimizi oluşturalım.
Arama Çubuğu Bileşenimizi Oluşturma
Arama Searchbar
bileşenimiz, film bileşenlerini aramak için bir arama çubuğu ve bir düğme bileşeni içerecek, hadi bunu aşağıda yapalım:
import React from 'react'; import styles from './Searchbar.module.css'; import { connect } from 'react-redux'; import { fetchMovie } from '../../actions'; import Movie from '../Movie/Movie'; class Searchbar extends React.Component{ render(){ return( <div className={styles.Form}> <div> <form onSubmit={this.formHandler}> <input type="text" placeholder="Movie Title" onChange={e => this.setState({title: e.target.value})} value={this.state.title}/> <button type="submit">Search</button> </form> </div> <Movie movie={this.props.movie}/> </div> ) } }
Yukarıdaki kodda, bir React bileşenini Redux deposuna bağlamak için kullanılan, bileşene mağazadan bilgi sağlayan ve ayrıca eylemleri mağazaya göndermek için kullanılan işlevleri sağlayan react-redux
connect
içe aktarıyoruz. Ardından, Action'dan Movie
bileşenini ve fetchMovie
işlevini içe aktardık.
Ardından, setState
kancasını kullanarak film başlıklarımızı girmek için bir giriş kutusu içeren bir form etiketimiz var, giriş kutusuna girilen değere title
durumunu ayarlayacak bir onChange
olayı ve değeri ekledik. Film başlıklarını aramak için bir button
etiketimiz var ve içe aktardığımız Movie
bileşenini kullanarak bileşenin özelliklerini, aramanın sonucuna props
olarak ilettik.
Sırada bize film başlığımızı API'ye gönderecek bir fonksiyon yazarak sonuçları gönderebilmemiz için, uygulamanın ilk durumunu da ayarlamamız gerekiyor. bunu aşağıda yapalım.
class Searchbar extends React.Component{ state = { title: '' } formHandler = (event) => { event.preventDefault(); this.props.fetchMovie(this.state.title); this.setState({title: ''}); }
Burada, uygulamanın ilk durumunu boş dizelere ayarladık, bir event parametresini alan ve fetchMovie
işlevini formHandler
geçiren ve başlığı uygulamanın yeni durumu olarak ayarlayan bir formHandler işlevi oluşturduk. Uygulamamızı tamamlamak için, bu bileşeni react-redux
redux'tan connect özelliğini kullanarak dışa aktaralım, bunu yapmak için bileşenimizin ihtiyaç duyacağı veri bölümünü seçmek için tepki redux mapToStateProps
özelliğini kullanırdık, mapToStateProps
hakkında daha fazla bilgiyi buradan edinebilirsiniz.
const mapStateToProps = (state) => { return { movie: state.movie } } export default connect(mapStateToProps, { fetchMovie })(Searchbar)
Searchbar.module.css
dosyası oluşturup aşağıdaki stilleri ekleyerek formumuza stiller ekleyelim:
.Form{ margin: 3rem auto; width: 80%; height: 100%; } input{ display: block; height: 45px; border: none; width: 100%; border-radius: 0.5rem; outline: none; padding: 0 1rem; } input:focus, select:focus{ border: 2px rgb(16, 204, 179) solid; } .Form button{ display: block; background: rgb(16, 204, 179); padding: 0.7rem; border-radius: 0.5rem; width: 20%; margin-top: 0.7rem; color: #FFF; border: none; text-decoration: none; transition: all 0.5s; } button:hover{ opacity: 0.6; } @media(max-width: 700px){ input{ height: 40px; padding: 0 1rem; } .Form button{ width: 40%; padding: 0.6rem; } }
Yukarıdakileri yaptıktan sonra, arama çubuğu bileşenimiz aşağıdaki resme benzer görünmelidir:
Uygulama İçin Eylem Oluşturma
Bu bileşende, uygulamamız için Redux eylemleri ayarlayacağız, İlk olarak, src
dizini içinde actions
adında bir klasör oluşturacağız ve klasörün içinde bir index.js
dosyası oluşturacağız. Burada, bir başlık parametresini alan ve Axios kullanarak API'den film getiren bir fetchMovie
işlevi yaratırdık. Bunu aşağıda yapalım:
import axios from 'axios'; export const fetchMovie = (title) => async (dispatch) => { const response = await axios.get( `https://cors-anywhere.herokuapp.com/https://www.omdbapi.com/?t=${title}&apikey=APIKEY`); dispatch({ type: 'FETCH_MOVIE', payload: response.data }) }
Yukarıdaki kodda, axios
içe aktardık ve async/await kullanarak bir title
parametresi alan fetchMovie
adlı bir işlev oluşturduk, böylece API sunucusuna istek yapabiliriz. Redux'a iletilen eylem nesnesini gönderen bir dispatch
işlevimiz var. Yukarıda sahip olduklarımızdan, FETCH_MOVIE
ve API'den aldığımız yanıtı içeren yükte bir eylem gönderiyoruz.
NOT: apikey
, OmdbAPI'ye kaydolduktan sonra kendi apikey
değiştirilecektir .
Uygulama Azaltıcıları Oluşturma
Bu bölümde uygulamamız için redüktörler oluşturacağız.
const fetchMovieReducer = (state = null, action) => { switch(action.type){ case 'FETCH_MOVIE': return action.payload; default: return state; } } const rootReducer = (state, action) => { return { movie: fetchMovieReducer(state, action) } } export default rootReducer;
Yukarıdaki kodda, bir switch operatörü kullanarak varsayılan bir null
durumu ve bir action
parametresi alan bir fetchMovieReducer
oluşturduk, action.payload
durumu için API'den aldığımız film olan FETCH_MOVIE
değerini döndüreceğiz. Gerçekleştirmeye çalıştığımız eylem redüktörde değilse, varsayılan durumumuza geri döneriz.
Ardından, mevcut durumu ve bir eylemi girdi olarak kabul edecek ve fetchMovieReducer'ı döndürecek bir rootReducer
işlevi fetchMovieReducer
.
bir araya getirmek
Bu bölümde index.js
içerisinde redux mağazamızı oluşturarak uygulamamızı bitirirdik, bunu aşağıda yapalım:
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import App from './App'; import 'bootstrap/dist/css/bootstrap.min.css'; import './index.css'; import reducers from './reducers'; const store = createStore(reducers, applyMiddleware(thunk)) ReactDOM.render( <Provider store={store}> <> <App/> </> </Provider>, document.getElementById('root') )
Yukarıdaki kodda oluşturduğumuz redüktör ve bir ara katman yazılımını geçerek createStore
yöntemini kullanarak uygulama store
oluşturduk. Ara yazılımlar, Redux'un işlevlerini geliştirmemize izin veren eklentilerdir. Burada applyMiddleware
kullanarak Redux Thunk ara yazılımından yararlanıyoruz. Mağazamızın eşzamansız güncellemeler yapması için Redux Thunk ara yazılımı gereklidir. Bu gereklidir çünkü varsayılan olarak Redux mağazayı eşzamanlı olarak günceller.
Uygulamamızın kullanılacak mağazayı tam olarak bildiğinden emin olmak için uygulamamızı bir Provider
bileşenine sardık ve mağazayı bir destek olarak geçtik, bunu yaparak uygulamamızdaki diğer bileşenler mağaza ile bağlantı kurabilir ve bilgi paylaşabilir.
index.css
dosyamıza biraz stil ekleyelim.
*{ margin: 0; padding: 0; box-sizing: border-box; } body{ background: rgb(15, 10, 34); color: #FFF; height: 100vh; max-width: 100%; }
Film Ayrıntı Bulucu Oluşturma ve Test Etme
Bu bölümde uygulamamızı App.js
render ederek uygulamamızı sonlandıracağız, bunun için App
adında sınıf tabanlı bir component oluşturalım ve Searchbar ve input alanımızı başlatalım.
import React from 'react'; import Searchbar from './components/Searchbar/Searchbar'; import styles from './App.module.css'; class App extends React.Component{ render(){ return( <div className={styles.App}> <h1 className={styles.Title}>Movies Search App</h1> <Searchbar/> </div> ) } } export default App;
Burada, Movie Search App yazan bir h1
ile App sınıfı tabanlı bir bileşen oluşturduk ve Searchbar
bileşenimizi ekledik. Uygulamamız aşağıdaki resim gibi görünmelidir:
Codesandbox'ta çalışan bir demo mevcuttur.
Çözüm
Redüktörler Redux durum yönetiminin önemli bir parçasıdır, redüktörler ile Redux uygulamalarımızın belirli alanlarını yan etkiler olmadan güncellemek için saf fonksiyonlar yazabiliriz. Redux redüktörlerinin temellerini, kullanımlarını ve redüktörler, durum ve argümanların temel kavramlarını öğrendik.
Redux redüktörlerle ilgili belgeleri burada görerek bunu daha da ileri götürebilirsiniz. Bunu daha da ileri götürebilir ve Redux redüktörleri üzerinde daha fazlasını inşa edebilirsiniz, ne inşa ettiğinizi bana bildirin.
Kaynaklar
- React-Redux belgeleri
- Redux belgeleri
-
connect()
işlevi -
applyMiddleware
işlevi