Summary

These notes cover React development topics, explaining concepts like JSX, components, props, and state management. Practical examples and best practices are included, making it a useful resource for learning React.

Full Transcript

§ npm create vite@latest 01-starting-project JSX JS eXtension - non standard js script Define target HTML structure and UI, not the steps to get there COMPONENT Two rules of component: 1. function must start with capital letter 2. function must return renderedable value to show on scre...

§ npm create vite@latest 01-starting-project JSX JS eXtension - non standard js script Define target HTML structure and UI, not the steps to get there COMPONENT Two rules of component: 1. function must start with capital letter 2. function must return renderedable value to show on screen PROPS Passing a Single Prop Object If you got data that's already organized as a JavaScript object, you can pass that object as a single prop value instead of splitting it across multiple props. I.e., instead of ​ or ​ you could also pass a single concept (or any name of your choice) prop to the CoreConcept component: ​ In the CoreConcept component, you would then get that one single prop: ​ export default function CoreConcept({ concept }) { ​ // Use concept.title, concept.description etc. ​ // Or destructure the concept object: const { title, description, image } = concept; ​ } It is entirely up to you which syntax & approach you prefer. Grouping Received Props Into a Single Object You can also pass multiple props to a component and then, in the component function, group them into a single object via JavaScript's "Rest Property" syntax. I.e., if a component is used like this: ​ You could group the received props into a single object like this: ​ export default function CoreConcept({...concept }) { ​ //...concept groups multiple values into a single object ​ // Use concept.title, concept.description etc. ​ // Or destructure the concept object: const { title, description, image } = concept; ​ } If that syntax is a bit confusing - worry not! You'll also see concrete examples for this syntax (and for why you might want to use it in certain situations) throughout the course! Default Prop Values Sometimes, you'll build components that may receive an optional prop. For example, a custom Button component may receive a type prop. So the Button component should be usable either with a type being set: ​ Or without it: ​ To make this component work, you might want to set a default value for the type prop - in case it's not passed. This can easily be achieved since JavaScript supports default values when using object destructuring: ​ export default function Button({ caption, type = "submit" }) { ​ // caption has no default value, type has a default value of "submit" ​ } COMPONENT COMPOSITION AND SPECIAL “CHILDREN” PROP ​ export default function TagButton(props) { return({props.children}); ​ } ​ ​ or with destructuring ​ export default function TagButton({ children }) { return({children}); ​ } ​ Children props refers to text or any complex JS structure if needed, between component tags Text to take as a children ONCLICK attribute The advantage of defining these event handle rfunctions inside the component function is that they then have access to the component's proprs and state. MANAGE STATE AND HOOKS React components execute only once! You have to tell them to execute again. useState - all functions started with use are reactHooks and need to be imported from react library, hooks can be used only inside component functions and they should be called on top level, so not nested in another function useState() creates an array with two elements - it will be always exactly two elements const stateArray = useState(‘Click here’) stateArray -> array produced and returned by React’s useState() function current data snapshot of execution in this execution cycle const [selectedTopic, setSelectedTopic] = useState(‘Click here’) ex.You're working on a part of an online shop where a discounted price should be displayed on the screen once the user clicked a button. Your task is to add an event listener to listen for clicks on the button that's already included in the App component. Upon a button click, the price should changefrom $100 to $75. Add a state value to the existing Appcomponent function and make sure the state value is both updated upon button clicks and output as part of the JSX code. --- Important: In this Udemy environment, you CAN'T import & use useState like this: ​ import { useState } from 'react'; ​... ​ useState(); Instead, import & use it like this (in your component): ​ import React from 'react'; ​... ​ React.useState(); import React from 'react'; export default function App() { const [value, setValue] = React.useState('$100') function calculateValue(value) { setValue(value) } return ( {value} setValue('$75')}>Apply Discount ); } Derived state/ computed value - Computed values are values that shouldn't be managed as separate state since they can be derived from other state RENDERING CONTENT CONDITIONALLY - 3 WAYS 1. ternary operator {!selectedTopic ? Please select topic :{EXAMPLES[selectedTopic].description}} 2. keeping jsx content in variable let tabContent = Please select topic if (selectedTopic ) { tabContent = {EXAMPLES[selectedTopic].description} } 3. && as condition statement - && will output phrase which is after it, if the statement before ampersand is true {!selectedTopic && Please select topic} DYNAMICALLY OUTPUT Key prop can be added to any component and to built-in-elements. Value for this key prop should be a value that uniquely identifies - here e.g. list item. Under the hood, it's used by React to efficiently render and update list. React should receive a unique "key" to help React tell the list items apart. export const CORE_CONCEPTS = [ { image: componentsImg, title: 'Components', description: 'The core UI building block - compose the user interface by combining multiple components.', }, { image: jsxImg, title: 'JSX', description: 'Return (potentially dynamic) HTML(ish) code to define the actual markup that will be rendered.', } ]; {CORE_CONCEPTS.map(concept => ) CoreConcepts to tablica, używamy map, a {} , [] ) Now, useEffect, unlike useState or useRef does not return a value, though. Instead, useEffect needs two arguments. And the first argument is a function that should wrap your side effect code. Instead, you should also pass second argument to useEffect. So, after this anonymous function, and that second argument is an array of dependencies of that effect function. So, if the app starts and the app component function executes, this code here will not be executed right away. Instead, it's only after the app component function execution finished. So, after this JSX code here has been returned. That this side effect function you passed to useEffect will be executed by React. So, React will execute that after the component function is done executing. If you define this dependencies arra, so, if you do not omit it, but you define it then, React will actually take a look at the dependencies specified there. And it will only execute this effect function again. If the dependency values changed. - taka funkcjonalność, która jest niezbędna do funkcjonowania aplikacji, ale nie wpływa na render cycle; jest potrzebna do aplikacji, ale nie jest głównym celem komponentu - bo jego głównym celem jest zwrócenie JSX code - pomoże synchronizować prop albo state values z do DOM API - przykład: tutaj useEfect jest super przydatne, bo jeśli byśmy zostawili tylko if statements, to kod jest wykonywany synchronicznie, leci od góry do dołu no i zmienna dialog nie zdążyła się jeszcze powiązać z zwracanym elementem dialog i wtedy if by wyrzucił błąd, że chcę wywołać metodę na undefined. A w momencie, kiedy wykonany jest z useEffect, cały kod się wykonuje oprócz useEffect, a dopiero po wykonaniu wszystkiego w komponencie wykona się useEffect, czyli już będą istniały powiazania. Effect dependencies: simply prop or state values that are used inside of this effect function. Mogą to też być functions or context values that depend on albo useState albo props. Dlatego musimy dodać open jako dependencies tutaj, więc open prop tutaj, a to gwarantuje, że ta dependencies zostanie teraz uruchomiona ponownie za każdym razem, gdy modal component function zostanie wykonana, a wartość open prop ulegnie zmianie. jeśli w mojej funkcji useEffect używam jakichś propsów albo state values, muszę dodać je jako dependencies, (np. [onConfirm, onCancel], ale w przypadku funkcji przekazywanej jako props, trzeba uważać, bo może utworzyć się infinite loop. - useCallback( function, [ dependencies] ) - hook, który ZWRACA inną funkcję,podaną jako pierwszy argument, przechowuje ją w cache i React ją zwróci (ale nie wywoła!) podczas re-renderowania komponentu - Podczas początkowego renderowania, useCallback zwraca przekazaną funkcję fn. - Podczas kolejnych renderowań albo zwróci już zapisaną funkcję fn z ostatniego renderowania (jeśli zależności nie uległy zmianie), albo zwróci funkcję fn przekazaną podczas tego renderowania. SET INTERVAL / CLEAR INTERVAL useEffect(() => { const interval = setInterval(() => { setRemainingTime((prevRemainingTime) => prevRemainingTime - 100); }, 100); //this cleanup function will then automatically be executed by React before it runs this effect function again, or when this component is unmounted from the DOM. return () => { clearInterval(interval); }; }, []); W React klucze (ang. keys) są ważnym elementem, który pomaga w optymalizacji wydajności i prawidłowym renderowaniu list elementów. Używając kluczy, React może efektywnie śledzić, które elementy wirtualnego DOM zostały zmienione, dodane lub usunięte. Poniżej znajdziesz dobre praktyki dotyczące stosowania kluczy w React. Dobre praktyki stosowania kluczy (keys) w React: Używaj unikalnych i stabilnych wartości jako kluczy: Klucz powinien być unikalny dla danego elementu listy i stabilny w czasie (niezmieniający się między renderami). Najczęściej używa się do tego unikalnych identyfikatorów, takich jak id z bazy danych. jsx Skopiuj kod const users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' } ]; return ( {users.map(user => ( {user.name} ))} ); 1. W powyższym przykładzie user.id to unikalna wartość, więc idealnie nadaje się na klucz. Unikaj używania indeksu tablicy jako klucza: Chociaż React pozwala na użycie indeksu tablicy jako klucza, jest to zalecane tylko w sytuacjach, gdy elementy listy nie zmieniają kolejności, nie są usuwane ani dodawane. Używanie indeksu może prowadzić do problemów z poprawnym zachowaniem komponentu, zwłaszcza jeśli elementy listy będą modyfikowane dynamicznie (dodawane, usuwane, przesuwane). Błędny przykład: jsx {users.map((user, index) => ( {user.name} ))} 2. W przypadku zmian w liście (dodawanie/usuwanie elementów), React może niewłaściwie zaktualizować DOM, ponieważ indeksy mogą się zmieniać. Klucz powinien być unikalny wśród rodzeństwa: Klucze muszą być unikalne tylko w ramach bezpośredniego rodzica, czyli rodzeństwa w tej samej liście. Nie muszą być globalnie unikalne w całym drzewie komponentów. jsx const articles = [ { id: 'a1', title: 'Article 1' }, { id: 'a2', title: 'Article 2' } ]; return ( {articles.map(article => ( {article.title} ))} ); 3. W tym przypadku klucze są unikalne w ramach elementów div będących rodzeństwem. 4. Nie używaj wartości, które mogą się zmieniać: Klucz musi być stabilny w czasie. Jeśli wartość, którą ustawisz jako klucz, może się zmienić między renderami, React może niepoprawnie dopasować elementy w drzewie DOM, co może prowadzić do niespodziewanych błędów. Dlatego unikalny i stały identyfikator (np. z bazy danych) jest lepszy niż dane, które mogą ulec zmianie (np. nazwa użytkownika). Pamiętaj o kluczach, gdy renderujesz elementy dynamicznie: Każdy element listy renderowanej dynamicznie przez metodę.map() lub.forEach() powinien mieć przypisany klucz, nawet jeśli lista jest generowana w ramach komponentu, który sam w sobie nie jest listą. Przykład: jsx function TodoList({ todos }) { return ( {todos.map(todo => ( ))} ); } 5. Klucze są wymagane tylko dla bezpośrednich dzieci w pętli: Jeśli masz komponent, który renderuje listę komponentów, to klucz powinien być dodany tylko do elementu bezpośrednio wewnątrz funkcji.map(). Nie musisz dodawać kluczy wewnątrz każdego komponentu z osobna. Przykład: jsx function TodoList({ todos }) { return ( {todos.map(todo => ( ))} ); } 6. W tym przypadku klucze są dodane do elementu TodoItem w funkcji.map(), a nie do każdego wewnętrznego elementu komponentu TodoItem. 7. Używaj kluczy nie tylko w listach li: Klucze nie są ograniczone tylko do elementów listy (). Powinny być używane za każdym razem, gdy dynamicznie renderujesz zestaw elementów, np. komponenty wewnątrz div lub table. 8. Ułatwiają śledzenie i debugowanie: Dzięki kluczom, React może lepiej śledzić elementy wirtualnego DOM, co poprawia wydajność aplikacji, zmniejsza liczbę niepotrzebnych renderów i ułatwia śledzenie zmian podczas debugowania. Podsumowanie: Używaj unikalnych i stabilnych wartości jako kluczy (np. id z bazy danych). Unikaj używania indeksów tablicy jako kluczy, chyba że lista jest statyczna i nie zmienia swojej kolejności. Klucze powinny być unikalne wśród rodzeństwa elementów. Używaj kluczy wszędzie tam, gdzie dynamicznie generujesz listy elementów, nawet jeśli nie są to standardowe elementy listy (li). Klucze są niezbędne do optymalizacji wydajności oraz poprawnego śledzenia i aktualizowania komponentów przez React. !!!Key ma również inne zastosowanie - może zostać dodany do komponentu, nie będąc częścią żadnej listy itp, ale to sprawi że React wyrenderuje komponent ponownie, jeśli key ulegnie zmianie. Key prop może być używany do reseting components.

Use Quizgecko on...
Browser
Browser