diff --git a/src/content/learn/extracting-state-logic-into-a-reducer.md b/src/content/learn/extracting-state-logic-into-a-reducer.md index 012a5c3f9..59f127c9f 100644 --- a/src/content/learn/extracting-state-logic-into-a-reducer.md +++ b/src/content/learn/extracting-state-logic-into-a-reducer.md @@ -1,25 +1,25 @@ --- -title: Extracting State Logic into a Reducer +title: State Mantığını Bir Reducer'a Aktarma --- -Components with many state updates spread across many event handlers can get overwhelming. For these cases, you can consolidate all the state update logic outside your component in a single function, called a _reducer._ +Birçok olay yöneticisine yayılmış çok fazla sayıda state güncellemesine sahip bileşenler can sıkıcı olabilir. Bu gibi durumlarda tüm state güncelleme mantıklarını _reducer_ (redüktör) adı verilen tek bir fonksiyonda birleştirebilirsiniz. -- What a reducer function is -- How to refactor `useState` to `useReducer` -- When to use a reducer -- How to write one well +- Bir reducer fonsiyonunun ne olduğu +- `useState`'i `useReducer` ile nasıl yeniden yapılandıracağınız +- Ne zaman bir reducer kullanmanız gerektiği +- İyi bir reducer yazmanın püf noktaları -## Consolidate state logic with a reducer {/*consolidate-state-logic-with-a-reducer*/} +## State mantığını (State logic) bir reducer ile birleştirin {/*consolidate-state-logic-with-a-reducer*/} -As your components grow in complexity, it can get harder to see at a glance all the different ways in which a component's state gets updated. For example, the `TaskApp` component below holds an array of `tasks` in state and uses three different event handlers to add, remove, and edit tasks: +Bileşenlerinizin karmaşıklığı arttıkça bir bileşenin state'inin hangi farklı yollarla güncellendiğini bir bakışta görmek zorlaşabilir. Örneğin, aşağıdaki `TaskApp` bileşeni `görevler` dizinini bir state'de tutar ve görevleri eklemek, kaldırmak ve düzenlemek için üç farklı olay yöneticisi kullanır: @@ -60,7 +60,7 @@ export default function TaskApp() { return ( <> -

Prague itinerary

+

Prag Gezisi Planı

setText(e.target.value)} /> @@ -96,7 +96,7 @@ export default function AddTask({onAddTask}) { setText(''); onAddTask(text); }}> - Add + Ekle ); @@ -133,14 +133,14 @@ function Task({task, onChange, onDelete}) { }); }} /> - + ); } else { taskContent = ( <> {task.text} - + ); } @@ -157,7 +157,7 @@ function Task({task, onChange, onDelete}) { }} /> {taskContent} - + ); } @@ -179,17 +179,17 @@ li {
-Each of its event handlers calls `setTasks` in order to update the state. As this component grows, so does the amount of state logic sprinkled throughout it. To reduce this complexity and keep all your logic in one easy-to-access place, you can move that state logic into a single function outside your component, **called a "reducer".** +Her bir olay yöneticisi state'i güncellemek için `setTasks`'ı çağırır. Bu bileşen büyüdükçe, içine serpiştirilmiş state mantığı miktarı da artar. Bu karmaşıklığı azaltmak ve tüm mantığı erişilmesi kolay tek bir yerde tutmak için state mantıklarını bileşeninizin dışında **"reducer" adı verilen** tek bir fonksiyona taşıyabilirsiniz. -Reducers are a different way to handle state. You can migrate from `useState` to `useReducer` in three steps: +Reducer'lar, state'i ele almanın farklı bir yöntemidir. `useState`'ten `useReducer`'a şu üç adımda geçebilirsiniz: -1. **Move** from setting state to dispatching actions. -2. **Write** a reducer function. -3. **Use** the reducer from your component. +1. State ayarlamak yerine işlemleri göndermeye (dispatching) **geçme**. +2. Bir reducer fonksiyonu **yazma**. +3. Bileşeninizden gelen “reducer”ı **kullanma**. -### Step 1: Move from setting state to dispatching actions {/*step-1-move-from-setting-state-to-dispatching-actions*/} +### Step 1: State ayarlamak yerine işlemleri göndermeye (dispatching) geçme {/*step-1-move-from-setting-state-to-dispatching-actions*/} -Your event handlers currently specify _what to do_ by setting state: +Olay yöneticileriniz şu aşamada _ne yapılacağını_ state ayarlayarak belirler: ```js function handleAddTask(text) { @@ -220,13 +220,14 @@ function handleDeleteTask(taskId) { } ``` -Remove all the state setting logic. What you are left with are three event handlers: +Tüm state ayarlama mantığını kaldırın. Geriye üç olay yöneticisi kalacaktır: -- `handleAddTask(text)` is called when the user presses "Add". -- `handleChangeTask(task)` is called when the user toggles a task or presses "Save". -- `handleDeleteTask(taskId)` is called when the user presses "Delete". +- `handleAddTask(text)` kullanıcı "Ekle" butonuna bastığı zaman çağrılır. +- `handleChangeTask(task)` kullanıcı bir görevi açıp kapattığında veya "Kaydet" butonuna bastığında çağrılır. +- `handleDeleteTask(taskId)` kullanıcı "Sil" butonuna bastığında çağrılır. + +Reducer'lar ile state yönetimi doğrudan state'i ayarlama işleminden biraz farklıdır. State ayarlayarak React'e "ne yapılacağını" belirtmek yerine, olay yöneticilerinden "işlemler" göndererek "kullanıcının ne yaptığını" belirtirsiniz. (State güncelleme mantığı başka bir yerde yaşayacaktır!) Yani bir olay yöneticisi aracılığıyla "görevleri ayarlamak" yerine, "görev eklendi/değiştirildi/silindi" şeklinde bir işlem gönderirsiniz. Bu kullanıcının isteğini daha açık hale getirir. -Managing state with reducers is slightly different from directly setting state. Instead of telling React "what to do" by setting state, you specify "what the user just did" by dispatching "actions" from your event handlers. (The state update logic will live elsewhere!) So instead of "setting `tasks`" via an event handler, you're dispatching an "added/changed/deleted a task" action. This is more descriptive of the user's intent. ```js function handleAddTask(text) { @@ -252,12 +253,12 @@ function handleDeleteTask(taskId) { } ``` -The object you pass to `dispatch` is called an "action": +`dispatch`'e gönderdiğiniz nesneye "işlem" adı verilir. ```js {3-7} function handleDeleteTask(taskId) { dispatch( - // "action" object: + // "işlem" nesnesi: { type: 'deleted', id: taskId, @@ -266,43 +267,42 @@ function handleDeleteTask(taskId) { } ``` -It is a regular JavaScript object. You decide what to put in it, but generally it should contain the minimal information about _what happened_. (You will add the `dispatch` function itself in a later step.) +Bu bildiğimiz bir JavaScript nesnesidir. İçine ne koyacağınıza siz karar verirsiniz, ancak genellikle _ne meydana geldiği_ hakkında minimum bilgi içermelidir. (`dispatch` fonksiyonunun kendisini daha sonraki bir adımda ekleyeceksiniz.) -An action object can have any shape. +Bir işlem nesnesi herhangi bir şekle sahip olabilir. -By convention, it is common to give it a string `type` that describes what happened, and pass any additional information in other fields. The `type` is specific to a component, so in this example either `'added'` or `'added_task'` would be fine. Choose a name that says what happened! +Geleneksel olarak, ona ne olduğunu açıklayan bir string `type`'ı vermek ve diğer alanlara herhangi bir ek bilgi girmek yaygındır. `type` bir bileşene özgüdür, bu nedenle bu örnek için `'added'` veya `'added_task'` uygun olacaktır. Ne olup bittiğini anlatan bir isim seçin! ```js dispatch({ - // specific to component + // bileşene özgüdür type: 'what_happened', - // other fields go here + // diğer alanlar buraya girilir }); ``` -### Step 2: Write a reducer function {/*step-2-write-a-reducer-function*/} +### Step 2: Bir reducer fonksiyonu yazma {/*step-2-write-a-reducer-function*/} -A reducer function is where you will put your state logic. It takes two arguments, the current state and the action object, and it returns the next state: +Bir reducer fonksiyonu state mantığınızı (state logic) koyacağınız yerdir. İki argüman alır; mevcut state ve işlem nesnesi, ardından bir sonraki state'i geri döndürür: ```js function yourReducer(state, action) { - // return next state for React to set + // React'in ayarlaması için bir sonraki state'i geri döndür } ``` +React reducer'dan ne geri döndürürseniz state'i ona göre ayarlayacaktır. -React will set the state to what you return from the reducer. - -To move your state setting logic from your event handlers to a reducer function in this example, you will: +Bu örnekte state ayarlama mantığınızı olay yöneticilerinden bir reducer fonksiyonuna taşımak için şunları yapacaksınız: -1. Declare the current state (`tasks`) as the first argument. -2. Declare the `action` object as the second argument. -3. Return the _next_ state from the reducer (which React will set the state to). +1. Geçerli state'i (`tasks`) ilk argüman olarak tanımlayın. +2. `action` nesnesini ikinci argüman olarak tanımlayın. +3. Reducer'dan (React'in state'i ayarlayacağı) bir sonraki state'i geri döndürün. -Here is all the state setting logic migrated to a reducer function: +Burada tüm state ayarlama mantığı tek bir reducer fonksiyonuna aktarılmıştır: ```js function tasksReducer(tasks, action) { @@ -326,18 +326,18 @@ function tasksReducer(tasks, action) { } else if (action.type === 'deleted') { return tasks.filter((t) => t.id !== action.id); } else { - throw Error('Unknown action: ' + action.type); + throw Error('Bilinmeyen işlem: ' + action.type); } } ``` -Because the reducer function takes state (`tasks`) as an argument, you can **declare it outside of your component.** This decreases the indentation level and can make your code easier to read. +Reducer fonksiyonu state'i (`tasks`) bir argüman olarak aldığından **bunu bileşeninizin dışında tanımlayabilirsiniz**. Bu satır girinti seviyesini azaltır ve kodunuzun okunmasını kolaylaştırır. -The code above uses if/else statements, but it's a convention to use [switch statements](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/switch) inside reducers. The result is the same, but it can be easier to read switch statements at a glance. +Yukarıdaki kod if/else ifadesini kullanır ancak [switch ifadesini](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/switch) reducer'ların içinde kullanmak bir gelenektir. Sonuç aynıdır, ancak switch ifadelerini bir bakışta okumak daha kolay olabilir. -We'll be using them throughout the rest of this documentation like so: +Bu dökümantasyonun geri kalanında bu şekilde kullanacağız: ```js function tasksReducer(tasks, action) { @@ -365,25 +365,25 @@ function tasksReducer(tasks, action) { return tasks.filter((t) => t.id !== action.id); } default: { - throw Error('Unknown action: ' + action.type); + throw Error('Bilinmeyen işlem: ' + action.type); } } } ``` -We recommend wrapping each `case` block into the `{` and `}` curly braces so that variables declared inside of different `case`s don't clash with each other. Also, a `case` should usually end with a `return`. If you forget to `return`, the code will "fall through" to the next `case`, which can lead to mistakes! +Farklı `case`'ler içinde bildirilen değişkenlerin birbiriyle çakışmaması için her `case` bloğunu `{` ve `}` küme parantezlerine sarmanızı öneririz. Ayrıca bir `case` genellikle bir `return` ile bitmelidir. Eğer `return`'u unutursanız, kod bir sonraki `case`'e "düşer" ve bu da hatalara yol açabilir! -If you're not yet comfortable with switch statements, using if/else is completely fine. +Eğer switch ifadeleri konusunda henüz rahat değilseniz, if/else kullanmaya devam edebilirsiniz. -#### Why are reducers called this way? {/*why-are-reducers-called-this-way*/} +#### Reducer'lar (redüktör) neden bu şekilde adlandırılır? {/*why-are-reducers-called-this-way*/} -Although reducers can "reduce" the amount of code inside your component, they are actually named after the [`reduce()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) operation that you can perform on arrays. +Reducer'lar bileşeninizin içindeki kod miktarını "azaltabilir" (reduce) olsa da, aslında diziler üzerinde gerçekleştirebileceğiniz [`reduce()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) metodundan almakta. -The `reduce()` operation lets you take an array and "accumulate" a single value out of many: +`reduce()` işlemi bir diziyi alıp birçok değeri tek bir değerde "toplamanızı" sağlar: ``` const arr = [1, 2, 3, 4, 5]; @@ -392,9 +392,9 @@ const sum = arr.reduce( ); // 1 + 2 + 3 + 4 + 5 ``` -The function you pass to `reduce` is known as a "reducer". It takes the _result so far_ and the _current item,_ then it returns the _next result._ React reducers are an example of the same idea: they take the _state so far_ and the _action_, and return the _next state._ In this way, they accumulate actions over time into state. +`reduce`'a aktardığınız fonksiyon "reducer" olarak bilinir. Bu fonksiyon _o ana kadarki sonucu_ ve _geçerli öğeyi_ alır, ardından _bir sonraki sonucu_ geri döndürür. React reducer'lar da aynı fikrin bir örneğidir: _o ana kadarki state'i_ ve _işlemi_ alırlar ve _bir sonraki state'i_ geri döndürürler. Bu şekilde, işlemleri zaman içinde state olarak toplarlar. -You could even use the `reduce()` method with an `initialState` and an array of `actions` to calculate the final state by passing your reducer function to it: +Hatta `reduce()` metodunu bir `initialState` ve bir `actions` dizisi ile kullanabilir ve reducer fonksiyonunuzu bu metoda aktararak son state'i hesaplayabilirsiniz: @@ -403,10 +403,10 @@ import tasksReducer from './tasksReducer.js'; let initialState = []; let actions = [ - {type: 'added', id: 1, text: 'Visit Kafka Museum'}, - {type: 'added', id: 2, text: 'Watch a puppet show'}, + {type: 'added', id: 1, text: 'Kafka Müzesini ziyaret et'}, + {type: 'added', id: 2, text: 'Kukla gösterisi izle'}, {type: 'deleted', id: 1}, - {type: 'added', id: 3, text: 'Lennon Wall pic'}, + {type: 'added', id: 3, text: "Lennon Duvarı'nda fotoğraf çek"}, ]; let finalState = actions.reduce(tasksReducer, initialState); @@ -441,7 +441,7 @@ export default function tasksReducer(tasks, action) { return tasks.filter((t) => t.id !== action.id); } default: { - throw Error('Unknown action: ' + action.type); + throw Error('Bilinmeyen işlem: ' + action.type); } } } @@ -453,43 +453,43 @@ export default function tasksReducer(tasks, action) { -You probably won't need to do this yourself, but this is similar to what React does! +Muhtemelen bunu kendiniz yapmanız gerekmeyecektir, ancak bu React'in yaptığına benzer! -### Step 3: Use the reducer from your component {/*step-3-use-the-reducer-from-your-component*/} +### Step 3: Bileşeninizden gelen "reducer"ı kullanma {/*step-3-use-the-reducer-from-your-component*/} -Finally, you need to hook up the `tasksReducer` to your component. Import the `useReducer` Hook from React: +En son olarak, `tasksReducer`'ı bileşeninize bağlamanız gerekiyor. `useReducer` Hook'unu React'ten içe aktarın: ```js import { useReducer } from 'react'; ``` -Then you can replace `useState`: +Daha sonra `useState`'i: ```js const [tasks, setTasks] = useState(initialTasks); ``` -with `useReducer` like so: +`useReducer` ile şu şekilde değiştirebilirsiniz: ```js const [tasks, dispatch] = useReducer(tasksReducer, initialTasks); ``` -The `useReducer` Hook is similar to `useState`—you must pass it an initial state and it returns a stateful value and a way to set state (in this case, the dispatch function). But it's a little different. +`useReducer` hook'u `useState`'e benzer; ona bir başlangıç state'i iletmeniz gerekir ve o da state bilgisi olan bir değeri geri döndürür (bu durumda dispatch fonksiyonu). Fakat yine de biraz faklılıklar gösterir. -The `useReducer` Hook takes two arguments: +`useReducer` hook'u iki argüman alır: -1. A reducer function -2. An initial state +1. Bir reduce fonksiyonu +2. Bir başlangıç state'i -And it returns: +Ve şunları geri döndürür: -1. A stateful value -2. A dispatch function (to "dispatch" user actions to the reducer) +1. State bilgisi içeren bir değer +2. Bir dispatch fonksiyonu (kullanıcı işlemleri reducer'a "göndermek" için) -Now it's fully wired up! Here, the reducer is declared at the bottom of the component file: +Artık tüm bağlantılar kurulmuş halde! Reducer burada bileşen dosyasının en altında tanımlanmıştır: @@ -525,7 +525,7 @@ export default function TaskApp() { return ( <> -

Prague itinerary

+

Prag Gezisi Planı

t.id !== action.id); } default: { - throw Error('Unknown action: ' + action.type); + throw Error('Bilinmeyen işlem: ' + action.type); } } } let nextId = 3; const initialTasks = [ - {id: 0, text: 'Visit Kafka Museum', done: true}, - {id: 1, text: 'Watch a puppet show', done: false}, - {id: 2, text: 'Lennon Wall pic', done: false}, + {id: 0, text: 'Kafka Müzesini ziyaret et', done: true}, + {id: 1, text: 'Kukla gösterisi izle', done: false}, + {id: 2, text: "Lennon Duvarı'nda fotoğraf çek", done: false}, ]; ``` @@ -582,7 +582,7 @@ export default function AddTask({onAddTask}) { return ( <> setText(e.target.value)} /> @@ -591,7 +591,7 @@ export default function AddTask({onAddTask}) { setText(''); onAddTask(text); }}> - Add + Ekle ); @@ -628,14 +628,14 @@ function Task({task, onChange, onDelete}) { }); }} /> - + ); } else { taskContent = ( <> {task.text} - + ); } @@ -652,7 +652,7 @@ function Task({task, onChange, onDelete}) { }} /> {taskContent} - + ); } @@ -674,7 +674,7 @@ li {
-If you want, you can even move the reducer to a different file: +Hatta isterseniz reducer'ı ayrı bir dosyaya da taşıyabilirsiniz: @@ -711,7 +711,7 @@ export default function TaskApp() { return ( <> -

Prague itinerary

+

Prag Gezisi Planı

t.id !== action.id); } default: { - throw Error('Unknown action: ' + action.type); + throw Error('Bilinmeyen işlem: ' + action.type); } } } @@ -770,7 +770,7 @@ export default function AddTask({onAddTask}) { return ( <> setText(e.target.value)} /> @@ -779,7 +779,7 @@ export default function AddTask({onAddTask}) { setText(''); onAddTask(text); }}> - Add + Ekle ); @@ -816,14 +816,14 @@ function Task({task, onChange, onDelete}) { }); }} /> - + ); } else { taskContent = ( <> {task.text} - + ); } @@ -840,7 +840,7 @@ function Task({task, onChange, onDelete}) { }} /> {taskContent} - + ); } @@ -862,30 +862,30 @@ li {
-Component logic can be easier to read when you separate concerns like this. Now the event handlers only specify _what happened_ by dispatching actions, and the reducer function determines _how the state updates_ in response to them. +Bileşen mantığını bu şekilde ayırmak okunarlığı daha kolay hale getirebilir. Artık olay yöneticileri işlemleri göndererek yalnızca _ne olduğunu_ belirler ve reducer fonksiyonu bunlara yanıt olarak _state'in nasıl güncelleneceği_ kararını verir. -## Comparing `useState` and `useReducer` {/*comparing-usestate-and-usereducer*/} +## `useState` ve `useReducer` karışılaştırması {/*comparing-usestate-and-usereducer*/} -Reducers are not without downsides! Here's a few ways you can compare them: +Reducers'ların dezavantajları da yok değil! İşte bunları karşılaştırabileceğiniz birkaç yol: -- **Code size:** Generally, with `useState` you have to write less code upfront. With `useReducer`, you have to write both a reducer function _and_ dispatch actions. However, `useReducer` can help cut down on the code if many event handlers modify state in a similar way. -- **Readability:** `useState` is very easy to read when the state updates are simple. When they get more complex, they can bloat your component's code and make it difficult to scan. In this case, `useReducer` lets you cleanly separate the _how_ of update logic from the _what happened_ of event handlers. -- **Debugging:** When you have a bug with `useState`, it can be difficult to tell _where_ the state was set incorrectly, and _why_. With `useReducer`, you can add a console log into your reducer to see every state update, and _why_ it happened (due to which `action`). If each `action` is correct, you'll know that the mistake is in the reducer logic itself. However, you have to step through more code than with `useState`. -- **Testing:** A reducer is a pure function that doesn't depend on your component. This means that you can export and test it separately in isolation. While generally it's best to test components in a more realistic environment, for complex state update logic it can be useful to assert that your reducer returns a particular state for a particular initial state and action. -- **Personal preference:** Some people like reducers, others don't. That's okay. It's a matter of preference. You can always convert between `useState` and `useReducer` back and forth: they are equivalent! +- **Kod miktarı:** Genellikle `useState` ile ilk etapta daha az kod yazmanız gerekir. `useReducer` ile ise hem reducer fonksiyonu _hem de_ dispatch işlemlerini yazmanız gerekir. Ne var ki, birçok olay yöneticisi state'i benzer şekillerde değiştiriyorsa, `useReducer` kodu azaltmaya yardımcı olabilir. +- **Okunabilirlik:** `useState` state güncellemeleri basit olduğu zamanlarda okunması da kolaydır. Daha karmaşık hale geldiklerinde ise bileşeninizin kodunu şişirebilir ve taranmasını zorlaştırabilir. Bu gibi durumlarda `useReducer`, güncelleme mantığının _nasıl_ olduğunu, olay yöneticilerinin _ne olduğundan_ temiz bir şekilde ayırmanızı sağlar. +- **Hata ayıklama:** `useState` ile ilgili bir hatanız olduğunda, state'in _nerede_ ve _neden_ yanlış ayarlandığını söylemek zor olabilir. `useReducer` ile, her state güncellemesini ve bunun neden olduğunu (hangi `işlem`'den kaynaklandığını) görmek için reducer'ınıza bir konsol logu ekleyebilirsiniz. Eğer bütün işlemler doğruysa, hatanın reducer mantığının kendisinde olduğunu bilirsiniz. Ancak, `useState` ile olduğundan daha fazla kod üzerinden geçmeniz gerekir. +- **Test etme:** Reducer, bileşeninize bağlı olmayan saf bir fonksiyondur. Bu, onu izole olarak ayrı ayrı dışa aktarabileceğiniz ve test edebileceğiniz anlamına gelir. Genellikle bileşenleri daha gerçekçi bir ortamda test etmek en iyisi olsa da karmaşık state güncelleme mantığı için reducer'unuzun belirli bir başlangıç state'i ve işlem için belirli bir state döndürdüğünü doğrulamak yararlı olabilir. +- **Kişisel tercih:** Bazı insanlar reducer'ları sever, bazıları sevmez. Bu sorun değil. Bu bir tercih meselesidir. Her zaman `useState` ve `useReducer` arasında dönüşümlü olarak geçiş yapabilirsiniz: bunlar eşdeğerdir! -We recommend using a reducer if you often encounter bugs due to incorrect state updates in some component, and want to introduce more structure to its code. You don't have to use reducers for everything: feel free to mix and match! You can even `useState` and `useReducer` in the same component. +Bazı bileşenlerde yanlış state güncellemeleri nedeniyle sık sık hatalarla karşılaşıyorsanız ve koda daha fazla yapılandırma getirmek istiyorsanız bir reducer kullanmanızı öneririz. Her şey için reducer kullanmak zorunda değilsiniz: farklı kombinler yapmaktan çekinmeyin! Hatta aynı bileşende `useState` ve `useReducer` bile kullanabilirsiniz. -## Writing reducers well {/*writing-reducers-well*/} +## İyi bir reducer yazmak {/*writing-reducers-well*/} -Keep these two tips in mind when writing reducers: +Reducer yazarken şu iki ipucunu aklınızda bulundurun: -- **Reducers must be pure.** Similar to [state updater functions](/learn/queueing-a-series-of-state-updates), reducers run during rendering! (Actions are queued until the next render.) This means that reducers [must be pure](/learn/keeping-components-pure)—same inputs always result in the same output. They should not send requests, schedule timeouts, or perform any side effects (operations that impact things outside the component). They should update [objects](/learn/updating-objects-in-state) and [arrays](/learn/updating-arrays-in-state) without mutations. -- **Each action describes a single user interaction, even if that leads to multiple changes in the data.** For example, if a user presses "Reset" on a form with five fields managed by a reducer, it makes more sense to dispatch one `reset_form` action rather than five separate `set_field` actions. If you log every action in a reducer, that log should be clear enough for you to reconstruct what interactions or responses happened in what order. This helps with debugging! +- **Reducer'lar saf olmalıdır.** [State güncelleme fonksiyonları](/learn/queueing-a-series-of-state-updates) gibi, reducer'lar da render sırasında çalışır! (İşlemler bir sonraki render işlemine kadar sıraya alınır.) Bunun anlamı reducer'ların [saf olması gerektiğidir](/learn/keeping-components-pure); aynı girdiler her zaman aynı çıktıyla sonuçlanır. Bunlar istek göndermemeli, zaman aşımı planlamamalı veya herhangi bir yan etki (bileşenin dışındaki şeyleri etkileyen faaliyetler) gerçekleştirmemelidir. [Nesneleri](/learn/updating-objects-in-state) ve [dizileri](/learn/updating-arrays-in-state) mutasyon (değişinim) olmadan güncellemelidirler. +- **Her işlem verilerde birden fazla değişikliğe yol açsa bile tek bir kullanıcı etkileşimini ifade eder.** Örneğin, bir reducer tarafından yönetilen beş alana sahip bir formda bir kullanıcı "Sıfırla" düğmesine bastığında, beş ayrı `set_field` işlemi yerine tek bir `reset_form` işlemini göndermek daha mantıklıdır. Bir reducer'daki her işlemi loglarsanız, bu log hangi etkileşimlerin veya yanıtların hangi sırayla gerçekleştiğini yeniden yapılandırmanız için yeterince açık olmalıdır. Bu, hata ayıklamaya yardımcı olur! -## Writing concise reducers with Immer {/*writing-concise-reducers-with-immer*/} +## Immer ile kısa reducer'lar yazma {/*writing-concise-reducers-with-immer*/} -Just like with [updating objects](/learn/updating-objects-in-state#write-concise-update-logic-with-immer) and [arrays](/learn/updating-arrays-in-state#write-concise-update-logic-with-immer) in regular state, you can use the Immer library to make reducers more concise. Here, [`useImmerReducer`](https://github.com/immerjs/use-immer#useimmerreducer) lets you mutate the state with `push` or `arr[i] =` assignment: +Aynı normal state'deki [nesneleri](/learn/updating-objects-in-state#write-concise-update-logic-with-immer) ve [dizileri güncelleme](/learn/updating-arrays-in-state#write-concise-update-logic-with-immer) gibi, Immer kütüphanesini reducer'ları daha kısa ve öz hale getirmek için kullanabilirsiniz. Burada, [`useImmerReducer`](https://github.com/immerjs/use-immer#useimmerreducer) işlevi `push` veya `arr[i] =` ataması ile state'i değiştirmenizi sağlar: @@ -913,7 +913,7 @@ function tasksReducer(draft, action) { return draft.filter((t) => t.id !== action.id); } default: { - throw Error('Unknown action: ' + action.type); + throw Error('Bilinmeyen işlem: ' + action.type); } } } @@ -945,7 +945,7 @@ export default function TaskApp() { return ( <> -

Prague itinerary

+

Prag Gezisi Planı

setText(e.target.value)} /> @@ -981,7 +981,7 @@ export default function AddTask({onAddTask}) { setText(''); onAddTask(text); }}> - Add + Ekle ); @@ -1018,14 +1018,14 @@ function Task({task, onChange, onDelete}) { }); }} /> - + ); } else { taskContent = ( <> {task.text} - + ); } @@ -1042,7 +1042,7 @@ function Task({task, onChange, onDelete}) { }} /> {taskContent} - + ); } @@ -1082,34 +1082,34 @@ li {
-Reducers must be pure, so they shouldn't mutate state. But Immer provides you with a special `draft` object which is safe to mutate. Under the hood, Immer will create a copy of your state with the changes you made to the `draft`. This is why reducers managed by `useImmerReducer` can mutate their first argument and don't need to return state. +Reducer'lar saf olmalıdır, dolayısıyla state'i değiştirmemelidirler. Ancak Immer size mutasyona uğraması güvenli olan özel bir `draft` nesnesi sağlar. Arka planda, Immer `draft`'ta yaptığınız değişikliklerle state'inizin bir kopyasını oluşturacaktır. Bu nedenle, `useImmerReducer` tarafından yönetilen reducer'lar ilk argümanlarını değiştirebilir ve state geri döndürmeleri gerekmez. -- To convert from `useState` to `useReducer`: - 1. Dispatch actions from event handlers. - 2. Write a reducer function that returns the next state for a given state and action. - 3. Replace `useState` with `useReducer`. -- Reducers require you to write a bit more code, but they help with debugging and testing. -- Reducers must be pure. -- Each action describes a single user interaction. -- Use Immer if you want to write reducers in a mutating style. +- `useState`'ten `useReducer`'a geçmek için: + 1. İşlemlerinizi olay yöneticilerinden gönderin. + 2. Belirli bir state ve action için bir sonraki state'i döndüren bir reducer fonksiyonu yazın. + 3. `useState`'i `useReducer` ile değiştirin. +- Reducer'lar biraz daha fazla kod yazmanızı gerektirse de hata ayıklama ve test etme konusunda yardımcı olurlar. +- Reducer'lar saf olmalıdır. +- Her işlem tek bir kullanıcı etkileşimini ifade eder. +- Reducer'ları mutasyona uğrayan bir biçimde yazmak istiyorsanız Immer kullanın. -#### Dispatch actions from event handlers {/*dispatch-actions-from-event-handlers*/} +#### İşlemleri olay yöneticisinden gönderin {/*dispatch-actions-from-event-handlers*/} -Currently, the event handlers in `ContactList.js` and `Chat.js` have `// TODO` comments. This is why typing into the input doesn't work, and clicking on the buttons doesn't change the selected recipient. +Şu anda, `ContactList.js` ve `Chat.js` içindeki olay yöneticilerinde `// TODO` yorumları var. Bu nedenle yazı alanına yazma özelliği çalışmıyor ve düğmelere tıklamak seçilen alıcı kişiyi değiştirmiyor. -Replace these two `// TODO`s with the code to `dispatch` the corresponding actions. To see the expected shape and the type of the actions, check the reducer in `messengerReducer.js`. The reducer is already written so you won't need to change it. You only need to dispatch the actions in `ContactList.js` and `Chat.js`. +Bu iki `// TODO`'yu ilgili işlemleri (actions) `dispatch` edecek kodla değiştirin. İşlemlerin beklenen şeklini ve türünü görmek için `messengerReducer.js` dosyasındaki reducer'u kontrol edin. Reducer hali hazırda yazılmıştır, bu yüzden değiştirmenize gerek yoktur. Yalnızca `ContactList.js` ve `Chat.js` içindeki işlemleri göndermeniz (dispatch) gerekir. -The `dispatch` function is already available in both of these components because it was passed as a prop. So you need to call `dispatch` with the corresponding action object. +Bu bileşenlerin her ikisinde de `dispatch` fonksiyonu zaten mevcuttur çünkü bir prop olarak aktarılmıştır. Bu yüzden `dispatch` fonksiyonunu ilgili işlem nesnesi ile çağırmanız gerekir. -To check the action object shape, you can look at the reducer and see which `action` fields it expects to see. For example, the `changed_selection` case in the reducer looks like this: +İşlem nesnesinin şeklini kontrol etmek için, reducer'a bakabilir ve hangi `action` alanlarını almayı beklediğini görebilirsiniz. Örneğin, reducer'daki `changed_selection` case'i şuna benzer: ```js case 'changed_selection': { @@ -1120,7 +1120,7 @@ case 'changed_selection': { } ``` -This means that your action object should have a `type: 'changed_selection'`. You also see the `action.contactId` being used, so you need to include a `contactId` property into your action. +Bu, işlem nesnenizin `type: 'changed_selection'` özelliğine sahip olması gerektiği anlamına gelir. Ayrıca `action.contactId` kullanıldığını görüyorsunuz, bu nedenle işlemlerinize bir `contactId` özelliği eklemeniz gerekir. @@ -1154,16 +1154,16 @@ export default function Messenger() { } const contacts = [ - {id: 0, name: 'Taylor', email: 'taylor@mail.com'}, - {id: 1, name: 'Alice', email: 'alice@mail.com'}, - {id: 2, name: 'Bob', email: 'bob@mail.com'}, + {id: 0, name: 'Deniz', email: 'deniz@mail.com'}, + {id: 1, name: 'Aylin', email: 'aylin@mail.com'}, + {id: 2, name: 'Ata', email: 'ata@mail.com'}, ]; ``` ```js messengerReducer.js export const initialState = { selectedId: 0, - message: 'Hello', + message: 'Merhaba', }; export function messengerReducer(state, action) { @@ -1182,7 +1182,7 @@ export function messengerReducer(state, action) { }; } default: { - throw Error('Unknown action: ' + action.type); + throw Error('Bilinmeyen işlem: ' + action.type); } } } @@ -1197,7 +1197,7 @@ export default function ContactList({contacts, selectedId, dispatch}) {
  • @@ -1217,14 +1217,14 @@ export default function Chat({contact, message, dispatch}) {