Redux Redüktörler Nasıl Çalışır?

Yayınlanan: 2022-03-10
Kısa özet ↬ state 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.

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

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:

bileşenler klasörü
Bileşenler klasörü. (Büyük önizleme)

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:

Arama çubuğu bileşeni
Arama çubuğu bileşeni. (Büyük önizleme)

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:

redüktörlü film detayları uygulaması
Redüktörler kullanılarak son film detayları uygulaması. (Büyük önizleme)

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