Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion content/docs/code-splitting.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ import("./math").then(math => {

When Webpack comes across this syntax, it automatically starts code-splitting
your app. If you're using Create React App, this is already configured for you
and you can [start using it](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#code-splitting) immediately. It's also supported
and you can [start using it](https://facebook.github.io/create-react-app/docs/code-splitting) immediately. It's also supported
out of the box in [Next.js](https://github.com/zeit/next.js/#dynamic-import).

If you're setting up Webpack yourself, you'll probably want to read Webpack's
Expand Down
40 changes: 34 additions & 6 deletions content/languages.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Status enums indicate what percentage of "core" content has been translated:
# 0: Incomplete (049%)
# 1: Partially complete (50–94%)
# 2: Complete (95–100%)
# 0: Incomplete (0-49%)
# 1: Partially complete (50-99%)
# 2: Complete (100%)

- name: English
translated_name: English
Expand All @@ -27,6 +27,10 @@
translated_name: Deutsch
code: de
status: 0
- name: Greek
translated_name: Ελληνικά
code: el
status: 0
- name: Spanish
translated_name: Español
code: es
Expand All @@ -38,6 +42,10 @@
- name: French
translated_name: Français
code: fr
status: 1
- name: Gujarati
translated_name: ગુજરાતી
code: gu
status: 0
- name: Hebrew
translated_name: עברית
Expand All @@ -62,11 +70,23 @@
- name: Japanese
translated_name: 日本語
code: ja
status: 1
status: 2
- name: Central Khmer
translated_name: ភាសាខ្មែរ
code: km
status: 0
- name: Korean
translated_name: 한국어
code: ko
status: 0
- name: Kurdish
translated_name: کوردی‎
code: ku
status: 0
- name: Lithuanian
translated_name: Lietuvių kalba
code: lt
status: 0
- name: Malayalam
translated_name: മലയാളം
code: ml
Expand Down Expand Up @@ -98,7 +118,7 @@
- name: Russian
translated_name: Русский
code: ru
status: 0
status: 1
- name: Sinhala
translated_name: සිංහල
code: si
Expand All @@ -107,13 +127,21 @@
translated_name: தமிழ்
code: ta
status: 0
- name: Telugu
translated_name: తెలుగు
code: te
status: 0
- name: Turkish
translated_name: Türkçe
code: tr
status: 0
- name: Ukrainian
translated_name: Українська
code: uk
status: 1
- name: Urdu
translated_name: اردو
code: ur
status: 0
- name: Uzbek
translated_name: Oʻzbekcha
Expand All @@ -126,7 +154,7 @@
- name: Simplified Chinese
translated_name: 简体中文
code: zh-hans
status: 0
status: 1
- name: Traditional Chinese
translated_name: 繁體中文
code: zh-hant
Expand Down
58 changes: 18 additions & 40 deletions content/tutorial/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,8 @@ Samouczek podzieliliśmy na kilka części:

Nie musisz wcale przechodzić przez wszystkie części samouczka naraz, żeby wynieść z niego cokolwiek. Spróbuj jednak dojść najdalej jak możesz - nawet jeśli będą to tylko dwa rozdziały.

W trakcie wykonywania poleceń możesz kopiować kod do edytora, ale zalecamy pisanie go samodzielnie. Pozwoli ci to bardziej skupić się na poszczególnych zagadnieniach, dzięki czemu lepiej je sobie przyswoisz i zrozumiesz.

### Co będziemy budować? {#what-are-we-building}

W tym samouczku pokażemy, jak przy pomocy Reacta zbudować interaktywną grę w "kółko i krzyżyk".

Na koniec nasz kod będzie wyglądał tak: **[Efekt końcowy](https://codepen.io/gaearon/pen/gWWZgR?editors=0010)**. Być może w tej chwili kod wygląda bez sensu albo nie rozumiesz jego składni, ale bez obaw! Celem tego samouczka jest właśnie pomóc ci zrozumieć Reacta i jego składnię.

Zanim przystąpisz do dalszej lektury, zachęcamy cię do uruchomienia gry w "kółko i krzyżyk". Zwróć uwagę, że jedną z funkcjonalności tej aplikacji jest, znajdująca się na prawo od planszy, numerowana lista. Wyświetla ona na bieżąco wszystkie wykonywane w danej rozgrywce ruchy.
Expand Down Expand Up @@ -190,6 +186,8 @@ Komponent `Square` (pole) renderuje pojedynczy element `<button>`, a `Board` (pl

Na dobry początek, spróbujmy przekazać jakieś dane z komponentu `Board` do `Square`.

W trakcie wykonywania poleceń zalecamy pisanie kodu samodzielnie. Pozwoli ci to bardziej skupić się na poszczególnych zagadnieniach, dzięki czemu lepiej je sobie przyswoisz i zrozumiesz.

W metodzie `renderSquare` komponentu `Board` przekaż komponentowi `Square` atrybut o nazwie `value` (pol. *wartość*):

```js{3}
Expand Down Expand Up @@ -242,7 +240,7 @@ class Square extends React.Component {
}
```

Teraz gdy klikniemy na polu, przeglądarka wyświetli wiadomość w oknie dialogowym.
Teraz gdy klikniesz na polu, przeglądarka wyświetli wiadomość w oknie dialogowym.

>Uwaga
>
Expand All @@ -260,7 +258,7 @@ Teraz gdy klikniemy na polu, przeglądarka wyświetli wiadomość w oknie dialog
>}
>```
>
>Zauważ, że za pomocą `onClick={() => alert('kliknięto w przycisk')}` pod atrybutem `onClick` przekazujemy *funkcję*. Zostanie ona wywołana dopiero po kliknięciu w przycisk. Częstym błędem jest zapominanie o `() =>` i pisanie `onClick={alert('kliknięto w przycisk')}`, co powoduje wyświetlenie wiadomości w momencie renderowania komponentu.
>Zauważ, że za pomocą `onClick={() => alert('kliknięto w przycisk')}` pod atrybutem `onClick` przekazujemy *funkcję*. React wywoła ją dopiero po kliknięciu w przycisk. Częstym błędem jest zapominanie o `() =>` i pisanie `onClick={alert('kliknięto w przycisk')}`, co powoduje wyświetlenie wiadomości w momencie renderowania komponentu.

W następnym kroku sprawimy, by komponent `Square` "pamiętał", że został kliknięty, i wyświetlał literę "X". Komponenty mogą "pamiętać" o różnych rzeczach dzięki **stanowi** (ang. *state*).

Expand Down Expand Up @@ -294,7 +292,7 @@ class Square extends React.Component {
Teraz zmienimy kod w metodzie `render` komponentu `Square` tak, aby po kliknięciu wyświetlał wartość aktualnego stanu:

* zamień `this.props.value` na `this.state.value` wewnątrz znacznika `<button>`,
* zamień procedurę obsługi zdarzenia `() => alert()` na `() => this.setState({value: 'X'})`,
* zamień procedurę obsługi zdarzenia `onClick={...}` na `onClick={() => this.setState({value: 'X'})}`,
* umieść atrybuty `className` i `onClick` w osobnych liniach dla lepszej czytelności kodu.

Po wprowadzeniu powyższych zmian, element `<button>`, zwracany przez komponent `Square`, powinien wyglądać następująco:
Expand Down Expand Up @@ -356,7 +354,9 @@ Być może przeszło ci przez myśl, że to komponent `Board` powinien "pytać"

**Aby móc zebrać dane z wielu komponentów potomnych lub umożliwić dwóm potomkom komunikowanie się ze sobą, należy zadeklarować ich wspólny stan w rodzicu. Taki rodzic może wtedy przekazać poszczególne wartości potomkom poprzez atrybuty; dzięki temu potomkowie będą zsynchronizowani zarówno ze sobą nawzajem, jak i z rodzicem.**

Wynoszenie stanu w górę struktury to dość częsty zabieg podczas refaktoryzacji (ang. *refactoring*) kodu. Wykorzystajmy zatem okazję do wypróbowania tego schematu. Dodajmy konstruktor do komponentu `Board` i ustawmy w nim stan przechowujący tablicę dziewięciu wartości `null`. Każdy z elementów tej tablicy będzie odpowiadał jednemu polu na planszy:
Wynoszenie stanu w górę struktury to dość częsty zabieg podczas refaktoryzacji (ang. *refactoring*) kodu. Wykorzystajmy zatem okazję do wypróbowania tego schematu.

Dodaj konstruktor do komponentu `Board` i ustaw w nim stan przechowujący tablicę dziewięciu wartości `null`. Każdy z elementów tej tablicy będzie odpowiadał jednemu polu na planszy:

```javascript{2-7}
class Board extends React.Component {
Expand All @@ -370,35 +370,9 @@ class Board extends React.Component {
renderSquare(i) {
return <Square value={i} />;
}

render() {
const status = 'Następny gracz: X';

return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
```

Gdy później wypełnimy planszę wartościami, tablica będzie wyglądała mniej więcej tak:
Gdy później wypełnimy planszę wartościami, tablica `this.state.squares` będzie wyglądała mniej więcej tak:

```javascript
[
Expand Down Expand Up @@ -432,7 +406,7 @@ Każde pole otrzyma poprzez atrybut `value` odpowiednio: `"X"`, `"O"` lub `null`

Następnie musimy zmienić zachowanie komponentu `Square` po kliknięciu na nim, ponieważ teraz to `Board` decyduje, które pola są wypełnione. Musimy zatem określić sposób, w jaki komponent `Square` może aktualizować stan swojego rodzica. Jako że stan komponentu `Board` należy tylko do niego, nie możemy tak po prostu nadpisać jego wartości z poziomu potomka `Square`.

Aby zapewnić komponentowi `Board` wyłączność na własność jego stanu, do komponentu `Square` przekażemy odpowiednią funkcję za pomocą atrybutów. Funkcja ta będzie wywoływana za każdym razem, gdy ktoś kliknie na pole. Zmieńmy więc metodę `renderSquare` w następujący sposób:
Zamiast tego, do komponentu `Square` przekażemy odpowiednią funkcję za pomocą atrybutów i sprawimy, by `Square` wywoływał ją za każdym razem, gdy ktoś kliknie na pole. Zmieńmy więc metodę `renderSquare` w następujący sposób:

```javascript{5}
renderSquare(i) {
Expand Down Expand Up @@ -478,11 +452,11 @@ Gdy użytkownik kliknie na pole, zostanie wywołana funkcja `onClick` dostarczon
2. Gdy użytkownik kliknie na przycisk, React wywoła procedurę obsługi zdarzenia `onClick` zdefiniowaną w metodzie `render()` komponentu `Square`.
3. Procedura ta wywoła funkcję `this.props.onClick()`, czyli atrybut przekazany przez komponent `Board`.
4. Ponieważ komponent `Board` przekazał swojemu potomkowi atrybut `onClick={() => this.handleClick(i)}`, kliknięcie w `Square` spowoduje w konsekwencji wywołanie `this.handleClick(i)` wewnątrz komponentu `Board`.
5. Nie zdefiniowaliśmy jeszcze metody `handleClick()`, dlatego aplikacja w tym momencie przestanie działać.
5. Nie zdefiniowaliśmy jeszcze metody `handleClick()`, dlatego aplikacja w tym momencie przestanie działać. Jeśli klikniesz na dowolne pole, zobaczysz błąd na czerwonym tle, mówiący coś w stylu: "this.handleClick is not a function" (pol. *this.handleClick nie jest funkcją*).

>Uwaga
>
>Atrybut `onClick` elementu DOM `<button>` ma dla Reacta specjalne znaczenie, ponieważ jest to wbudowany komponent. W przypadku własny komponentów, jak `Square`, nazwa tego atrybutu może być dowolna. Moglibyśmy nazwać inaczej zarówno atrybut `onClick` w `Square`, jak i `handleClick` w `Board`. Przyjęło się jednak określać atrybuty odpowiedzialne za wywołanie zdarzenia jako `on[Event]`, a procedury obsługi zdarzeń jako `handle[Event]`.
>Atrybut `onClick` elementu DOM `<button>` ma dla Reacta specjalne znaczenie, ponieważ jest to wbudowany komponent. W przypadku własny komponentów, jak `Square`, nazwa tego atrybutu może być dowolna. Moglibyśmy nazwać inaczej zarówno atrybut `onClick` w `Square`, jak i `handleClick` w `Board`, a kod nadal działałby w taki sam sposób. Przyjęło się jednak określać atrybuty odpowiedzialne za wywołanie zdarzenia jako `on[Event]`, a procedury obsługi zdarzeń jako `handle[Event]`.

Jeśli teraz klikniemy na polę planszy, otrzymamy błąd, ponieważ nie zdefiniowaliśmy jeszcze metody `handleClick`. Dodajmy ją zatem:

Expand Down Expand Up @@ -643,7 +617,9 @@ Za każdym razem, gdy użytkownik wykona ruch, zmienna `xIsNext` (typu zerojedyn
}
```

Po tej modyfikacji "krzyżyki" i "kółka" będą wykonywać ruchy na zmianę. Zaktualizujmy teraz wartość `status` w metodzie `render`, aby poprawnie wyświetlała, który gracz jest następny:
Po tej modyfikacji "krzyżyki" i "kółka" będą wykonywać ruchy na zmianę. Spróbuj zagrać!

Zaktualizujmy teraz wartość `status` w metodzie `render`, aby poprawnie wyświetlała, który gracz jest następny:

```javascript{2}
render() {
Expand Down Expand Up @@ -714,7 +690,7 @@ class Board extends React.Component {

### Ogłaszanie zwycięzcy {#declaring-a-winner}

Teraz gdy już wyświetlamy, który z graczy będzie wykonywał następny ruch, powinniśmy również ogłaszać zwycięzcę lub wyświetlać informację o braku możliwych ruchów. Do wyłaniania zwycięzcy posłuży nam następujące funkcja pomocnicza, którą należy dodać na końcu pliku:
Teraz gdy już wyświetlamy, który z graczy będzie wykonywał następny ruch, powinniśmy również ogłaszać zwycięzcę lub wyświetlać informację o braku możliwych ruchów. Do wyłaniania zwycięzcy posłuży nam następująca funkcja pomocnicza, którą należy dodać na końcu pliku:

```javascript
function calculateWinner(squares) {
Expand All @@ -738,6 +714,8 @@ function calculateWinner(squares) {
}
```

Dla dowolnej tablicy z dziewięcioma polami sprawdzi ona, który z graczy wygrał, a następnie zwróci odpowiednio: `'X'`, `'O'` lub `null`.

Funkcję `calculateWinner(squares)` wywołamy w metodzie `render` komponentu `Board`, sprawdzając w ten sposób, czy gracz aktualnie wykonujący ruch jest zwycięzcą. Jeśli odpowiedź będzie pozytywna, możemy wyświetlić tekst w stylu "Wygrywa: X" lub "Wygrywa: O". Podmieńmy `status` w metodzie `render` na:

```javascript{2-8}
Expand Down