diff --git a/src/content/learn/choosing-the-state-structure.md b/src/content/learn/choosing-the-state-structure.md
index 5be2b4d3..27241bb4 100644
--- a/src/content/learn/choosing-the-state-structure.md
+++ b/src/content/learn/choosing-the-state-structure.md
@@ -1,53 +1,53 @@
---
-title: Choosing the State Structure
+title: Odabir strukture state-a
---
-Structuring state well can make a difference between a component that is pleasant to modify and debug, and one that is a constant source of bugs. Here are some tips you should consider when structuring state.
+Pravilno strukturiranje state-a može napraviti razliku između komponente koju je lako menjati i debug-ovati, i one koja je stalan izvor bug-ova. Ovde se nalazi par saveta koje trebate razmotriti kada strukturirate state.
-* When to use a single vs multiple state variables
-* What to avoid when organizing state
-* How to fix common issues with the state structure
+* Kada da koristite jednu ili više state promenljivih
+* Šta izbegavati prilikom organizacije state-a
+* Kako popraviti česte probleme sa strukturom state-a
-## Principles for structuring state {/*principles-for-structuring-state*/}
+## Principi za strukturiranje state-a {/*principles-for-structuring-state*/}
-When you write a component that holds some state, you'll have to make choices about how many state variables to use and what the shape of their data should be. While it's possible to write correct programs even with a suboptimal state structure, there are a few principles that can guide you to make better choices:
+Kada pišete komponentu koja sadrži neki state, moraćete da odlučite koliko state promenljivih da koristite i kakav oblik podataka u njima vam je potreban. Iako je moguće da napišete pravilan program sa neoptimizovanom strukturom state-a, postoji par principa koji vas mogu uputiti da donesete bolje odluke:
-1. **Group related state.** If you always update two or more state variables at the same time, consider merging them into a single state variable.
-2. **Avoid contradictions in state.** When the state is structured in a way that several pieces of state may contradict and "disagree" with each other, you leave room for mistakes. Try to avoid this.
-3. **Avoid redundant state.** If you can calculate some information from the component's props or its existing state variables during rendering, you should not put that information into that component's state.
-4. **Avoid duplication in state.** When the same data is duplicated between multiple state variables, or within nested objects, it is difficult to keep them in sync. Reduce duplication when you can.
-5. **Avoid deeply nested state.** Deeply hierarchical state is not very convenient to update. When possible, prefer to structure state in a flat way.
+1. **Grupisati povezane state-ove.** Ako uvek istovremeno ažurirate dve ili više state promenljivih, pokušajte da ih spojite u jednu state promenljivu.
+2. **Izbegavati kontradikcije u state-u.** Kada je state strukturiran tako da više delova state-a budu kontradiktorni i "neodgovarajući" jedni drugima, ostavljate prostora za greške. Pokušajte ovo da izbegnete.
+3. **Izbegavati suvišan state.** Ako, tokom renderovanja, neku informaciju možete izračunati na osnovu props-a komponente ili već postojeće state promenljive, ne biste trebali da stavite tu informaciju u state komponente.
+4. **Izbegavati dupliranje u state-u.** Kada su isti podaci duplirani u više state promenljivih, ili unutar ugnježdenih objekata, teško je sinhronizovati ih. Smanjite dupliranje kada to možete.
+5. **Izbegavati duboko ugnježedeni state.** Hijerarhijski dubok state nije zgodan za ažuriranje. Kada je moguće, preferirajte da strukturirate state da bude flat.
-The goal behind these principles is to *make state easy to update without introducing mistakes*. Removing redundant and duplicate data from state helps ensure that all its pieces stay in sync. This is similar to how a database engineer might want to ["normalize" the database structure](https://docs.microsoft.com/en-us/office/troubleshoot/access/database-normalization-description) to reduce the chance of bugs. To paraphrase Albert Einstein, **"Make your state as simple as it can be--but no simpler."**
+Cilj iza ovih principa je da *napravite da se state lako ažurira bez uvođenja grešaka*. Uklanjanje suvišnih i dupliranih podataka iz state-a pomaže da svi njegovi delovi ostanu sinhronizovani. Ovo je slično onome kako inženjeri baza podataka žele da ["normalizuju" strukturu baze podataka](https://docs.microsoft.com/en-us/office/troubleshoot/access/database-normalization-description) i smanje šanse za bug-ove. Da parafraziramo Alberta Ajnštajna, **"Napravite vaš state što jednostavnijim--ali ne jednostavnijim od toga."**
-Now let's see how these principles apply in action.
+Hajde da vidimo primenu ovih principa na delu.
-## Group related state {/*group-related-state*/}
+## Grupisati povezane state-ove {/*group-related-state*/}
-You might sometimes be unsure between using a single or multiple state variables.
+Ponekad se možete dvoumiti između upotrebe jedne ili više state promenljivih.
-Should you do this?
+Da li koristiti ovo?
```js
const [x, setX] = useState(0);
const [y, setY] = useState(0);
```
-Or this?
+Ili ovo?
```js
const [position, setPosition] = useState({ x: 0, y: 0 });
```
-Technically, you can use either of these approaches. But **if some two state variables always change together, it might be a good idea to unify them into a single state variable.** Then you won't forget to always keep them in sync, like in this example where moving the cursor updates both coordinates of the red dot:
+Tehnički, možete koristiti oba pristupa. Ali, **ako se dve state promenljive uvek menjaju zajedno, može biti dobra ideja da ih grupišete u jednu state promenljivu**. Tako nećete zaboravati da ih držite sinhronizovane, kao u ovom primeru gde pomeranje kursora ažurira obe koordinate crvene tačke:
@@ -93,17 +93,17 @@ body { margin: 0; padding: 0; height: 250px; }
-Another case where you'll group data into an object or an array is when you don't know how many pieces of state you'll need. For example, it's helpful when you have a form where the user can add custom fields.
+Drugi slučaj gde možete grupisati podatke u objekat ili niz je kada ne znate koliko state-ova vam treba. Na primer, korisno je kada imate formu gde korisnik može uneti polja po sopstvenoj želji.
-If your state variable is an object, remember that [you can't update only one field in it](/learn/updating-objects-in-state) without explicitly copying the other fields. For example, you can't do `setPosition({ x: 100 })` in the above example because it would not have the `y` property at all! Instead, if you wanted to set `x` alone, you would either do `setPosition({ ...position, x: 100 })`, or split them into two state variables and do `setX(100)`.
+Ako vam je state promenljiva objekat, zapamtite da [ne možete ažurirati samo jedno polje u njemu](/learn/updating-objects-in-state) bez eksplicitnog kopiranja ostalih polja. Na primer, ne možete napisati `setPosition({ x: 100 })` u primeru iznad jer nemate `y` polje uopšte! Umesto toga, ako želite da postavite samo `x`, napisaćete `setPosition({ ...position, x: 100 })`, ili ćete ih podeliti u dve state promenljive i napisati `setX(100)`.
-## Avoid contradictions in state {/*avoid-contradictions-in-state*/}
+## Izbegavati kontradikcije u state-u {/*avoid-contradictions-in-state*/}
-Here is a hotel feedback form with `isSending` and `isSent` state variables:
+Ovde je feedback forma za hotel sa `isSending` i `isSent` state promenljivama:
@@ -124,12 +124,12 @@ export default function FeedbackForm() {
}
if (isSent) {
- return
Thanks for feedback!
+ return
Hvala za feedback!
}
return (
);
}
-// Pretend to send a message.
+// Pretvaraj se da šalješ poruku.
function sendMessage(text) {
return new Promise(resolve => {
setTimeout(resolve, 2000);
@@ -157,9 +157,9 @@ function sendMessage(text) {
-While this code works, it leaves the door open for "impossible" states. For example, if you forget to call `setIsSent` and `setIsSending` together, you may end up in a situation where both `isSending` and `isSent` are `true` at the same time. The more complex your component is, the harder it is to understand what happened.
+Iako ovaj kod radi, ostavlja prostor za "nemoguća" stanja. Na primer, ako zaboravite da pozovete `setIsSent` i `setIsSending` zajedno, možete završiti u situaciji gde su i `isSending` i `isSent` postavljeni na `true` istovremeno. Što je vaša komponenta kompleksnija, teže je razumeti šta se desilo.
-**Since `isSending` and `isSent` should never be `true` at the same time, it is better to replace them with one `status` state variable that may take one of *three* valid states:** `'typing'` (initial), `'sending'`, and `'sent'`:
+**Pošto `isSending` i `isSent` nikad ne bi trebali da budu `true` istovremeno, bolje je zameniti ih sa jednom `status` state promenljivom koja može imati jedno od *tri* validna stanja:** `'typing'` (inicijalno), `'sending'` i `'sent'`:
@@ -181,12 +181,12 @@ export default function FeedbackForm() {
const isSent = status === 'sent';
if (isSent) {
- return
Thanks for feedback!
+ return
Hvala za feedback!
}
return (
);
}
-// Pretend to send a message.
+// Pretvaraj se da šalješ poruku.
function sendMessage(text) {
return new Promise(resolve => {
setTimeout(resolve, 2000);
@@ -214,20 +214,20 @@ function sendMessage(text) {
-You can still declare some constants for readability:
+Možete deklarisati konstante da poboljšate čitljivost:
```js
const isSending = status === 'sending';
const isSent = status === 'sent';
```
-But they're not state variables, so you don't need to worry about them getting out of sync with each other.
+Ali, one nisu state promenljive, pa ne morate brinuti o tome da li će biti sinhronizovane.
-## Avoid redundant state {/*avoid-redundant-state*/}
+## Izbegavati suvišan state {/*avoid-redundant-state*/}
-If you can calculate some information from the component's props or its existing state variables during rendering, you **should not** put that information into that component's state.
+Ako, tokom renderovanja, neku informaciju možete izračunati na osnovu props-a komponente ili već postojeće state promenljive, **ne biste** trebali da stavite tu informaciju u state komponente.
-For example, take this form. It works, but can you find any redundant state in it?
+Na primer, pogledajte ovu formu. Radi, ali, da li možete pronaći neki suvišan state u njoj?
@@ -251,23 +251,23 @@ export default function Form() {
return (
<>
-
Let’s check you in
+
Prijavite se
- Your ticket will be issued to: {fullName}
+ Vaša karta će biti izdata na ime: {fullName}
>
);
@@ -280,9 +280,9 @@ label { display: block; margin-bottom: 5px; }
-This form has three state variables: `firstName`, `lastName`, and `fullName`. However, `fullName` is redundant. **You can always calculate `fullName` from `firstName` and `lastName` during render, so remove it from state.**
+Ova forma ima tri state promenljive: `firstName`, `lastName` i `fullName`. Međutim, `fullName` je suvišno. **Uvek možete izračunati `fullName` pomoću `firstName` i `lastName` tokom rendera, pa je uklonite iz state-a.**
-This is how you can do it:
+Evo kako to da uradite:
@@ -305,23 +305,23 @@ export default function Form() {
return (
<>
-
Let’s check you in
+
Prijavite se
- Your ticket will be issued to: {fullName}
+ Vaša karta će biti izdata na ime: {fullName}
>
);
@@ -334,50 +334,50 @@ label { display: block; margin-bottom: 5px; }
-Here, `fullName` is *not* a state variable. Instead, it's calculated during render:
+Ovde, `fullName` *nije* state promenljiva. Umesto toga, računa se tokom rendera:
```js
const fullName = firstName + ' ' + lastName;
```
-As a result, the change handlers don't need to do anything special to update it. When you call `setFirstName` or `setLastName`, you trigger a re-render, and then the next `fullName` will be calculated from the fresh data.
+Kao rezultat, handler-i za promenu ne moraju ništa posebno da rade da bi je ažurirali. Kada pozovete `setFirstName` ili `setLastName`, pokrećete ponovni render, a onda će naredni `fullName` biti izračunat na osnovu najnovijih podataka.
-#### Don't mirror props in state {/*don-t-mirror-props-in-state*/}
+#### Ne preslikavajte props-e u state {/*don-t-mirror-props-in-state*/}
-A common example of redundant state is code like this:
+Uobičajen primer suvišnog state-a je ovakav kod:
```js
function Message({ messageColor }) {
const [color, setColor] = useState(messageColor);
```
-Here, a `color` state variable is initialized to the `messageColor` prop. The problem is that **if the parent component passes a different value of `messageColor` later (for example, `'red'` instead of `'blue'`), the `color` *state variable* would not be updated!** The state is only initialized during the first render.
+Ovde, `color` state promenljiva je inicijalizovana na `messageColor` prop. Problem je u tome što **ako roditeljska komponenta prosledi drugu vrednost za `messageColor` kasnije (na primer, `'red'` umesto `'blue'`), `color` *state promenljiva* neće biti ažurirana**! State je inicijalizovan samo tokom prvog rendera.
-This is why "mirroring" some prop in a state variable can lead to confusion. Instead, use the `messageColor` prop directly in your code. If you want to give it a shorter name, use a constant:
+Zato "preslikavanje" nekog prop-a u state promenljivu može dovesti do zabune. Umesto toga, koristite `messageColor` prop direktno u kodu. Ako želite da mu date kraće ime, koristite konstantu:
```js
function Message({ messageColor }) {
const color = messageColor;
```
-This way it won't get out of sync with the prop passed from the parent component.
+Na ovaj način neće ostati nesinhronzovan sa prop-om prosleđenim iz roditeljske komponente.
-"Mirroring" props into state only makes sense when you *want* to ignore all updates for a specific prop. By convention, start the prop name with `initial` or `default` to clarify that its new values are ignored:
+"Preslikavanje" props-a u state ima smisla jedino ako *želite* da ignorišete sve promene tog prop-a. Po konvenciji, nazovite prop tako da počinje sa `initial` ili `default` da ukažete na to da će nove vrednosti biti ignorisane:
```js
function Message({ initialColor }) {
- // The `color` state variable holds the *first* value of `initialColor`.
- // Further changes to the `initialColor` prop are ignored.
+ // `color` state promenljiva drži *prvu* vrednost `initialColor`-a.
+ // Naredne promene `initialColor` prop-a su ignorisane.
const [color, setColor] = useState(initialColor);
```
-## Avoid duplication in state {/*avoid-duplication-in-state*/}
+## Izbegavati dupliranje u state-u {/*avoid-duplication-in-state*/}
-This menu list component lets you choose a single travel snack out of several:
+Ova komponenta vam omogućava da odaberete jednu grickalicu za put od nekoliko ponuđenih:
@@ -385,9 +385,9 @@ This menu list component lets you choose a single travel snack out of several:
import { useState } from 'react';
const initialItems = [
- { title: 'pretzels', id: 0 },
- { title: 'crispy seaweed', id: 1 },
- { title: 'granola bar', id: 2 },
+ { title: 'perece', id: 0 },
+ { title: 'hrskave morske alge', id: 1 },
+ { title: 'musli pločica', id: 2 },
];
export default function Menu() {
@@ -398,7 +398,7 @@ export default function Menu() {
return (
<>
-
>
);
}
@@ -422,9 +422,9 @@ button { margin-top: 10px; }
-Currently, it stores the selected item as an object in the `selectedItem` state variable. However, this is not great: **the contents of the `selectedItem` is the same object as one of the items inside the `items` list.** This means that the information about the item itself is duplicated in two places.
+Trenutno se čuva izabrana stavka kao objekat u `selectedItem` state promenljivoj. Međutim, ovo nije dobro: **sadržaj `selectedItem`-a je isti objekat koji se nalazi unutar stavke u `items` listi**. Ovo znači da je informacija o stavki duplirana na dva mesta.
-Why is this a problem? Let's make each item editable:
+Zašto je ovo problem? Hajde da dodamo izmenu stavki:
@@ -432,9 +432,9 @@ Why is this a problem? Let's make each item editable:
import { useState } from 'react';
const initialItems = [
- { title: 'pretzels', id: 0 },
- { title: 'crispy seaweed', id: 1 },
- { title: 'granola bar', id: 2 },
+ { title: 'perece', id: 0 },
+ { title: 'hrskave morske alge', id: 1 },
+ { title: 'musli pločica', id: 2 },
];
export default function Menu() {
@@ -458,7 +458,7 @@ export default function Menu() {
return (
<>
-
>
);
}
@@ -487,9 +487,9 @@ button { margin-top: 10px; }
-Notice how if you first click "Choose" on an item and *then* edit it, **the input updates but the label at the bottom does not reflect the edits.** This is because you have duplicated state, and you forgot to update `selectedItem`.
+Primetite da ako prvo kliknete "Izaberi", a *onda* izmenite stavku, **input se ažurira, ali labela na dnu ne prikazuje unete promene**. To je zato što imate dupliran state, a zaboravili ste da ažurirate `selectedItem`.
-Although you could update `selectedItem` too, an easier fix is to remove duplication. In this example, instead of a `selectedItem` object (which creates a duplication with objects inside `items`), you hold the `selectedId` in state, and *then* get the `selectedItem` by searching the `items` array for an item with that ID:
+Iako možete ažurirati i `selectedItem` takođe, lakše je ukloniti dupliranje. U ovom primeru, umesto `selectedItem` objekta (koji kreira dupliranje sa objektima unutar `items` liste), vi čuvate `selectedId` u state-u, a *onda* `selectedItem` dobijate pretraživanjem `items`-a preko tog ID-a:
@@ -497,9 +497,9 @@ Although you could update `selectedItem` too, an easier fix is to remove duplica
import { useState } from 'react';
const initialItems = [
- { title: 'pretzels', id: 0 },
- { title: 'crispy seaweed', id: 1 },
- { title: 'granola bar', id: 2 },
+ { title: 'perece', id: 0 },
+ { title: 'hrskave morske alge', id: 1 },
+ { title: 'musli pločica', id: 2 },
];
export default function Menu() {
@@ -525,7 +525,7 @@ export default function Menu() {
return (
<>
-
>
);
}
@@ -554,23 +554,23 @@ button { margin-top: 10px; }
-The state used to be duplicated like this:
+State koji je dupliran izgleda ovako:
-* `items = [{ id: 0, title: 'pretzels'}, ...]`
-* `selectedItem = {id: 0, title: 'pretzels'}`
+* `items = [{ id: 0, title: 'perece'}, ...]`
+* `selectedItem = {id: 0, title: 'perece'}`
-But after the change it's like this:
+Ali, nakon promene, sada izgleda ovako:
-* `items = [{ id: 0, title: 'pretzels'}, ...]`
+* `items = [{ id: 0, title: 'perece'}, ...]`
* `selectedId = 0`
-The duplication is gone, and you only keep the essential state!
+Dupliranja nema, a ostaje samo obavezan state!
-Now if you edit the *selected* item, the message below will update immediately. This is because `setItems` triggers a re-render, and `items.find(...)` would find the item with the updated title. You didn't need to hold *the selected item* in state, because only the *selected ID* is essential. The rest could be calculated during render.
+Sada, ako izmenite *izabranu* stavku, poruka ispod će se odmah ažurirati. To se dešava jer `setItems` pokreće ponovni render, a `items.find(...)` će pronaći stavku sa ažuriranim nazivom. Nije vam potrebno da čuvate *izabranu stavku* u state-u, zato što je jedino *izabrani ID* obavezan. Ostatak može biti izračunat tokom rendera.
-## Avoid deeply nested state {/*avoid-deeply-nested-state*/}
+## Izbegavati duboko ugnježedeni state {/*avoid-deeply-nested-state*/}
-Imagine a travel plan consisting of planets, continents, and countries. You might be tempted to structure its state using nested objects and arrays, like in this example:
+Zamislite plan putovanja koji sadrži planete, kontinente i države. Možete biti u iskušenju da strukturirate state upotrebom ugnježdenih objekata i nizova, kao u ovom primeru:
@@ -599,7 +599,7 @@ export default function TravelPlan() {
const planets = plan.childPlaces;
return (
<>
-
Places to visit
+
Mesta za posetu
{planets.map(place => (
@@ -616,42 +616,42 @@ export const initialTravelPlan = {
title: '(Root)',
childPlaces: [{
id: 1,
- title: 'Earth',
+ title: 'Zemlja',
childPlaces: [{
id: 2,
- title: 'Africa',
+ title: 'Afrika',
childPlaces: [{
id: 3,
- title: 'Botswana',
+ title: 'Bocvana',
childPlaces: []
}, {
id: 4,
- title: 'Egypt',
+ title: 'Egipat',
childPlaces: []
}, {
id: 5,
- title: 'Kenya',
+ title: 'Kenija',
childPlaces: []
}, {
id: 6,
- title: 'Madagascar',
+ title: 'Madagaskar',
childPlaces: []
}, {
id: 7,
- title: 'Morocco',
+ title: 'Maroko',
childPlaces: []
}, {
id: 8,
- title: 'Nigeria',
+ title: 'Nigerija',
childPlaces: []
}, {
id: 9,
- title: 'South Africa',
+ title: 'Južna Afrika',
childPlaces: []
}]
}, {
id: 10,
- title: 'Americas',
+ title: 'Amerika',
childPlaces: [{
id: 11,
title: 'Argentina',
@@ -666,71 +666,71 @@ export const initialTravelPlan = {
childPlaces: []
}, {
id: 14,
- title: 'Canada',
+ title: 'Kanada',
childPlaces: []
}, {
id: 15,
- title: 'Jamaica',
+ title: 'Jamajka',
childPlaces: []
}, {
id: 16,
- title: 'Mexico',
+ title: 'Meksiko',
childPlaces: []
}, {
id: 17,
- title: 'Trinidad and Tobago',
+ title: 'Trinidad i Tobago',
childPlaces: []
}, {
id: 18,
- title: 'Venezuela',
+ title: 'Venecuela',
childPlaces: []
}]
}, {
id: 19,
- title: 'Asia',
+ title: 'Azija',
childPlaces: [{
id: 20,
- title: 'China',
+ title: 'Kina',
childPlaces: []
}, {
id: 21,
- title: 'India',
+ title: 'Indija',
childPlaces: []
}, {
id: 22,
- title: 'Singapore',
+ title: 'Singapur',
childPlaces: []
}, {
id: 23,
- title: 'South Korea',
+ title: 'Južna Koreja',
childPlaces: []
}, {
id: 24,
- title: 'Thailand',
+ title: 'Tajland',
childPlaces: []
}, {
id: 25,
- title: 'Vietnam',
+ title: 'Vijetnam',
childPlaces: []
}]
}, {
id: 26,
- title: 'Europe',
+ title: 'Evropa',
childPlaces: [{
id: 27,
- title: 'Croatia',
+ title: 'Hrvatska',
childPlaces: [],
}, {
id: 28,
- title: 'France',
+ title: 'Francuska',
childPlaces: [],
}, {
id: 29,
- title: 'Germany',
+ title: 'Nemačka',
childPlaces: [],
}, {
id: 30,
- title: 'Italy',
+ title: 'Italija',
childPlaces: [],
}, {
id: 31,
@@ -738,39 +738,39 @@ export const initialTravelPlan = {
childPlaces: [],
}, {
id: 32,
- title: 'Spain',
+ title: 'Španija',
childPlaces: [],
}, {
id: 33,
- title: 'Turkey',
+ title: 'Turska',
childPlaces: [],
}]
}, {
id: 34,
- title: 'Oceania',
+ title: 'Okeanija',
childPlaces: [{
id: 35,
- title: 'Australia',
+ title: 'Australija',
childPlaces: [],
}, {
id: 36,
- title: 'Bora Bora (French Polynesia)',
+ title: 'Bora Bora (Francuska Polinezija)',
childPlaces: [],
}, {
id: 37,
- title: 'Easter Island (Chile)',
+ title: 'Uskršnje ostrvo (Čile)',
childPlaces: [],
}, {
id: 38,
- title: 'Fiji',
+ title: 'Fidži',
childPlaces: [],
}, {
id: 39,
- title: 'Hawaii (the USA)',
+ title: 'Havaji (SAD)',
childPlaces: [],
}, {
id: 40,
- title: 'New Zealand',
+ title: 'Novi Zeland',
childPlaces: [],
}, {
id: 41,
@@ -780,18 +780,18 @@ export const initialTravelPlan = {
}]
}, {
id: 42,
- title: 'Moon',
+ title: 'Mesec',
childPlaces: [{
id: 43,
- title: 'Rheita',
+ title: 'Rheita krater',
childPlaces: []
}, {
id: 44,
- title: 'Piccolomini',
+ title: 'Piccolomini krater',
childPlaces: []
}, {
id: 45,
- title: 'Tycho',
+ title: 'Tihov krater',
childPlaces: []
}]
}, {
@@ -812,11 +812,11 @@ export const initialTravelPlan = {
-Now let's say you want to add a button to delete a place you've already visited. How would you go about it? [Updating nested state](/learn/updating-objects-in-state#updating-a-nested-object) involves making copies of objects all the way up from the part that changed. Deleting a deeply nested place would involve copying its entire parent place chain. Such code can be very verbose.
+Recimo da želite dodati dugme za brisanje mesta koje ste već posetili. Kako biste to uradili? [Ažuriranje ugnježdenog state-a](/learn/updating-objects-in-state#updating-a-nested-object) podrazumeva pravljenje kopija svih objekata od mesta koje se promenilo na gore. Brisanje duboko ugnježdenog mesta bi zahtevalo kopiranje celokupnog lanca roditeljskih objekata. Takav kod može biti veoma opširan.
-**If the state is too nested to update easily, consider making it "flat".** Here is one way you can restructure this data. Instead of a tree-like structure where each `place` has an array of *its child places*, you can have each place hold an array of *its child place IDs*. Then store a mapping from each place ID to the corresponding place.
+**Ako je state previše ugnježden da bi se lako ažurirao, razmotrite da ga napravite da bude "flat".** Ovde je jedan način da restrukturirate ove podatke. Umesto strukture nalik na stablo gde svaki `place` ima niz *dečjih mesta*, možete napraviti da svako mesto čuva niz *ID-eva dečjih mesta*. Onda napravite mapiranje od ID-a mesta do odgovarajućeg mesta.
-This data restructuring might remind you of seeing a database table:
+Ovo restrukturiranje podataka vas može podsetiti na tabelu u bazi podataka:
@@ -851,7 +851,7 @@ export default function TravelPlan() {
const planetIds = root.childIds;
return (
<>
-
Places to visit
+
Mesta za posetu
{planetIds.map(id => (
-**Now that the state is "flat" (also known as "normalized"), updating nested items becomes easier.**
+**Sada, kada je state "flat" (poznato i pod nazivom "normalizovano"), ažuriranje ugnježdenih stavki postaje lakše.**
-In order to remove a place now, you only need to update two levels of state:
+Da biste uklonili mesto, potrebno je ažurirati dva nivoa state-a:
-- The updated version of its *parent* place should exclude the removed ID from its `childIds` array.
-- The updated version of the root "table" object should include the updated version of the parent place.
+- Ažurirana verzija njegovog *roditeljskog* mesta treba da isključi uklonjeni ID iz `childIds` niza.
+- Ažurirana verzija root "tabela" objekta treba da uključi ažuriranu verziju roditeljskog mesta.
-Here is an example of how you could go about it:
+Ovde je primer kako to možete uraditi:
@@ -1138,17 +1138,17 @@ export default function TravelPlan() {
function handleComplete(parentId, childId) {
const parent = plan[parentId];
- // Create a new version of the parent place
- // that doesn't include this child ID.
+ // Kreiraj novu verziju roditeljskog mesta
+ // koji ne sadrži ovaj ID deteta.
const nextParent = {
...parent,
childIds: parent.childIds
.filter(id => id !== childId)
};
- // Update the root state object...
+ // Ažuriraj root state objekat...
setPlan({
...plan,
- // ...so that it has the updated parent.
+ // ...tako da ima ažuriranog roditelja.
[parentId]: nextParent
});
}
@@ -1157,7 +1157,7 @@ export default function TravelPlan() {
const planetIds = root.childIds;
return (
<>
-
Places to visit
+
Mesta za posetu
{planetIds.map(id => (
{
onComplete(parentId, id);
}}>
- Complete
+ Kompetiraj
{childIds.length > 0 &&
@@ -1211,52 +1211,52 @@ export const initialTravelPlan = {
},
1: {
id: 1,
- title: 'Earth',
+ title: 'Zemlja',
childIds: [2, 10, 19, 26, 34]
},
2: {
id: 2,
- title: 'Africa',
+ title: 'Afrika',
childIds: [3, 4, 5, 6 , 7, 8, 9]
},
3: {
id: 3,
- title: 'Botswana',
+ title: 'Bocvana',
childIds: []
},
4: {
id: 4,
- title: 'Egypt',
+ title: 'Egipat',
childIds: []
},
5: {
id: 5,
- title: 'Kenya',
+ title: 'Kenija',
childIds: []
},
6: {
id: 6,
- title: 'Madagascar',
+ title: 'Madagaskar',
childIds: []
},
7: {
id: 7,
- title: 'Morocco',
+ title: 'Maroko',
childIds: []
},
8: {
id: 8,
- title: 'Nigeria',
+ title: 'Nigerija',
childIds: []
},
9: {
id: 9,
- title: 'South Africa',
+ title: 'Južna Afrika',
childIds: []
},
10: {
id: 10,
- title: 'Americas',
+ title: 'Amerika',
childIds: [11, 12, 13, 14, 15, 16, 17, 18],
},
11: {
@@ -1276,87 +1276,87 @@ export const initialTravelPlan = {
},
14: {
id: 14,
- title: 'Canada',
+ title: 'Kanada',
childIds: []
},
15: {
id: 15,
- title: 'Jamaica',
+ title: 'Jamajka',
childIds: []
},
16: {
id: 16,
- title: 'Mexico',
+ title: 'Meksiko',
childIds: []
},
17: {
id: 17,
- title: 'Trinidad and Tobago',
+ title: 'Trinidad i Tobago',
childIds: []
},
18: {
id: 18,
- title: 'Venezuela',
+ title: 'Venecuela',
childIds: []
},
19: {
id: 19,
- title: 'Asia',
+ title: 'Azija',
childIds: [20, 21, 22, 23, 24, 25],
},
20: {
id: 20,
- title: 'China',
+ title: 'Kina',
childIds: []
},
21: {
id: 21,
- title: 'India',
+ title: 'Indija',
childIds: []
},
22: {
id: 22,
- title: 'Singapore',
+ title: 'Singapur',
childIds: []
},
23: {
id: 23,
- title: 'South Korea',
+ title: 'Južna Koreja',
childIds: []
},
24: {
id: 24,
- title: 'Thailand',
+ title: 'Tajland',
childIds: []
},
25: {
id: 25,
- title: 'Vietnam',
+ title: 'Vijetnam',
childIds: []
},
26: {
id: 26,
- title: 'Europe',
+ title: 'Evropa',
childIds: [27, 28, 29, 30, 31, 32, 33],
},
27: {
id: 27,
- title: 'Croatia',
+ title: 'Hrvatska',
childIds: []
},
28: {
id: 28,
- title: 'France',
+ title: 'Francuska',
childIds: []
},
29: {
id: 29,
- title: 'Germany',
+ title: 'Nemačka',
childIds: []
},
30: {
id: 30,
- title: 'Italy',
+ title: 'Italija',
childIds: []
},
31: {
@@ -1366,47 +1366,47 @@ export const initialTravelPlan = {
},
32: {
id: 32,
- title: 'Spain',
+ title: 'Španija',
childIds: []
},
33: {
id: 33,
- title: 'Turkey',
+ title: 'Turska',
childIds: []
},
34: {
id: 34,
- title: 'Oceania',
+ title: 'Okeanija',
childIds: [35, 36, 37, 38, 39, 40, 41],
},
35: {
id: 35,
- title: 'Australia',
+ title: 'Australija',
childIds: []
},
36: {
id: 36,
- title: 'Bora Bora (French Polynesia)',
+ title: 'Bora Bora (Francuska Polinezija)',
childIds: []
},
37: {
id: 37,
- title: 'Easter Island (Chile)',
+ title: 'Uskršnje ostrvo (Čile)',
childIds: []
},
38: {
id: 38,
- title: 'Fiji',
+ title: 'Fidži',
childIds: []
},
39: {
id: 39,
- title: 'Hawaii (the USA)',
+ title: 'Havaji (SAD)',
childIds: []
},
40: {
id: 40,
- title: 'New Zealand',
+ title: 'Novi Zeland',
childIds: []
},
41: {
@@ -1416,22 +1416,22 @@ export const initialTravelPlan = {
},
42: {
id: 42,
- title: 'Moon',
+ title: 'Mesec',
childIds: [43, 44, 45]
},
43: {
id: 43,
- title: 'Rheita',
+ title: 'Rheita krater',
childIds: []
},
44: {
id: 44,
- title: 'Piccolomini',
+ title: 'Piccolomini krater',
childIds: []
},
45: {
id: 45,
- title: 'Tycho',
+ title: 'Tihov krater',
childIds: []
},
46: {
@@ -1458,13 +1458,13 @@ button { margin: 10px; }
-You can nest state as much as you like, but making it "flat" can solve numerous problems. It makes state easier to update, and it helps ensure you don't have duplication in different parts of a nested object.
+Možete ugnjezditi state koliko god želite, ali pravljenje "flat" state-a može rešiti dosta problema. Čini da ažuriranje state-a bude lakše, a takođe i osigurava da nemate dupliranje u različitim delovima ugnježdenog objekta.
-#### Improving memory usage {/*improving-memory-usage*/}
+#### Poboljšanje upotrebe memorije {/*improving-memory-usage*/}
-Ideally, you would also remove the deleted items (and their children!) from the "table" object to improve memory usage. This version does that. It also [uses Immer](/learn/updating-objects-in-state#write-concise-update-logic-with-immer) to make the update logic more concise.
+Idealno, takođe bi uklanjali obrisane stavke (i njihovu decu!) iz "tabela" objekta da biste poboljšali upotrebu memorije. Ova verzija to radi. Takođe [koristi Immer](/learn/updating-objects-in-state#write-concise-update-logic-with-immer) kako bi učinila logiku ažuriranja konciznijom.
@@ -1477,12 +1477,12 @@ export default function TravelPlan() {
function handleComplete(parentId, childId) {
updatePlan(draft => {
- // Remove from the parent place's child IDs.
+ // Ukloni iz ID-eva roditeljskog mesta.
const parent = draft[parentId];
parent.childIds = parent.childIds
.filter(id => id !== childId);
- // Forget this place and all its subtree.
+ // Zaboravi ovo mesto i sva njegova podstabla.
deleteAllChildren(childId);
function deleteAllChildren(id) {
const place = draft[id];
@@ -1496,7 +1496,7 @@ export default function TravelPlan() {
const planetIds = root.childIds;
return (
<>
-
Places to visit
+
Mesta za posetu
{planetIds.map(id => (
{
onComplete(parentId, id);
}}>
- Complete
+ Kompetiraj
{childIds.length > 0 &&
@@ -1550,52 +1550,52 @@ export const initialTravelPlan = {
},
1: {
id: 1,
- title: 'Earth',
+ title: 'Zemlja',
childIds: [2, 10, 19, 26, 34]
},
2: {
id: 2,
- title: 'Africa',
+ title: 'Afrika',
childIds: [3, 4, 5, 6 , 7, 8, 9]
},
3: {
id: 3,
- title: 'Botswana',
+ title: 'Bocvana',
childIds: []
},
4: {
id: 4,
- title: 'Egypt',
+ title: 'Egipat',
childIds: []
},
5: {
id: 5,
- title: 'Kenya',
+ title: 'Kenija',
childIds: []
},
6: {
id: 6,
- title: 'Madagascar',
+ title: 'Madagaskar',
childIds: []
},
7: {
id: 7,
- title: 'Morocco',
+ title: 'Maroko',
childIds: []
},
8: {
id: 8,
- title: 'Nigeria',
+ title: 'Nigerija',
childIds: []
},
9: {
id: 9,
- title: 'South Africa',
+ title: 'Južna Afrika',
childIds: []
},
10: {
id: 10,
- title: 'Americas',
+ title: 'Amerika',
childIds: [11, 12, 13, 14, 15, 16, 17, 18],
},
11: {
@@ -1615,87 +1615,87 @@ export const initialTravelPlan = {
},
14: {
id: 14,
- title: 'Canada',
+ title: 'Kanada',
childIds: []
},
15: {
id: 15,
- title: 'Jamaica',
+ title: 'Jamajka',
childIds: []
},
16: {
id: 16,
- title: 'Mexico',
+ title: 'Meksiko',
childIds: []
},
17: {
id: 17,
- title: 'Trinidad and Tobago',
+ title: 'Trinidad i Tobago',
childIds: []
},
18: {
id: 18,
- title: 'Venezuela',
+ title: 'Venecuela',
childIds: []
},
19: {
id: 19,
- title: 'Asia',
+ title: 'Azija',
childIds: [20, 21, 22, 23, 24, 25,],
},
20: {
id: 20,
- title: 'China',
+ title: 'Kina',
childIds: []
},
21: {
id: 21,
- title: 'India',
+ title: 'Indija',
childIds: []
},
22: {
id: 22,
- title: 'Singapore',
+ title: 'Singapur',
childIds: []
},
23: {
id: 23,
- title: 'South Korea',
+ title: 'Južna Koreja',
childIds: []
},
24: {
id: 24,
- title: 'Thailand',
+ title: 'Tajland',
childIds: []
},
25: {
id: 25,
- title: 'Vietnam',
+ title: 'Vijetnam',
childIds: []
},
26: {
id: 26,
- title: 'Europe',
+ title: 'Evropa',
childIds: [27, 28, 29, 30, 31, 32, 33],
},
27: {
id: 27,
- title: 'Croatia',
+ title: 'Hrvatska',
childIds: []
},
28: {
id: 28,
- title: 'France',
+ title: 'Francuska',
childIds: []
},
29: {
id: 29,
- title: 'Germany',
+ title: 'Nemačka',
childIds: []
},
30: {
id: 30,
- title: 'Italy',
+ title: 'Italija',
childIds: []
},
31: {
@@ -1705,47 +1705,47 @@ export const initialTravelPlan = {
},
32: {
id: 32,
- title: 'Spain',
+ title: 'Španija',
childIds: []
},
33: {
id: 33,
- title: 'Turkey',
+ title: 'Turska',
childIds: []
},
34: {
id: 34,
- title: 'Oceania',
+ title: 'Okeanija',
childIds: [35, 36, 37, 38, 39, 40,, 41],
},
35: {
id: 35,
- title: 'Australia',
+ title: 'Australija',
childIds: []
},
36: {
id: 36,
- title: 'Bora Bora (French Polynesia)',
+ title: 'Bora Bora (Francuska Polinezija)',
childIds: []
},
37: {
id: 37,
- title: 'Easter Island (Chile)',
+ title: 'Uskršnje ostrvo (Čile)',
childIds: []
},
38: {
id: 38,
- title: 'Fiji',
+ title: 'Fidži',
childIds: []
},
39: {
id: 39,
- title: 'Hawaii (the USA)',
+ title: 'Havaji (SAD)',
childIds: []
},
40: {
id: 40,
- title: 'New Zealand',
+ title: 'Novi Zeland',
childIds: []
},
41: {
@@ -1755,22 +1755,22 @@ export const initialTravelPlan = {
},
42: {
id: 42,
- title: 'Moon',
+ title: 'Mesec',
childIds: [43, 44, 45]
},
43: {
id: 43,
- title: 'Rheita',
+ title: 'Rheita krater',
childIds: []
},
44: {
id: 44,
- title: 'Piccolomini',
+ title: 'Piccolomini krater',
childIds: []
},
45: {
id: 45,
- title: 'Tycho',
+ title: 'Tihov krater',
childIds: []
},
46: {
@@ -1817,25 +1817,25 @@ button { margin: 10px; }
-Sometimes, you can also reduce state nesting by moving some of the nested state into the child components. This works well for ephemeral UI state that doesn't need to be stored, like whether an item is hovered.
+Ponekad, možete smanjiti ugnježdenost state-a pomeranjem nekih ugnježdenih objekata u dečje komponente. Ovo radi dobro za kratkotrajne UI state-ove koji ne moraju biti čuvani, kao što je podatak da li se prelazi mišem iznad neke stavke.
-* If two state variables always update together, consider merging them into one.
-* Choose your state variables carefully to avoid creating "impossible" states.
-* Structure your state in a way that reduces the chances that you'll make a mistake updating it.
-* Avoid redundant and duplicate state so that you don't need to keep it in sync.
-* Don't put props *into* state unless you specifically want to prevent updates.
-* For UI patterns like selection, keep ID or index in state instead of the object itself.
-* If updating deeply nested state is complicated, try flattening it.
+* Ako se dve state promenljive uvek istovremeno ažuriraju, pokušajte da ih spojite u jednu.
+* Pažljivo birajte state promenljive da biste izbegli kreiranje "nemogućih" stanja.
+* Strukturirajte state na način koji smanjuje šanse za pravljenje grešaka prilikom ažuriranja.
+* Izbegavajte suvišan i dupliran state kako ne biste morali da ih sinhronizujete.
+* Ne stavljajte props *unutar* state-a osim ako specifično želite da sprečite ažuriranja.
+* Za UI šablone poput odabira, u state-u čuvajte ID ili indeks umesto celog objekta.
+* Ako je ažuriranje duboko ugnježdenog state-a komplikovano, probajte da ga flatten-ujete.
-#### Fix a component that's not updating {/*fix-a-component-thats-not-updating*/}
+#### Popraviti komponentu koja se ne ažurira {/*fix-a-component-thats-not-updating*/}
-This `Clock` component receives two props: `color` and `time`. When you select a different color in the select box, the `Clock` component receives a different `color` prop from its parent component. However, for some reason, the displayed color doesn't update. Why? Fix the problem.
+Ova `Clock` komponenta prima dva props-a: `color` i `time`. Kada izaberete drugu boju iz dropdown-a, `Clock` komponenta primi drugačiji `color` prop iz svoje roditeljske komponente. Međutim, iz nekog razloga, prikazana boja se ne ažurira. Zašto? Popravite problem.
@@ -1873,7 +1873,7 @@ export default function App() {
return (