React Components
Fonksiyon component örneği:
function App() {
return (
<div>Hello world!</div>
);
}
React Props
Ana bileşenden alt component'e geçirilen veriler props olarak adlandırılır.Prop'lar (properties) salt okunur değişmez bileşenlerdir ve herhangi bir javascript değeri componentlerde dahil olmak üzere prop olarak iletilebilir.
Fonksiyon component için örnek prop kullanımı:
function App() {
return <User name="John Doe" />
}
function User(props) {
return <h1>Hello, {props.name}</h1>; // Hello, John Doe!
}
Object destructuring yöntemi ile prop kullanımı:
function App() {
return <User name="John Doe" />
}
function User({ name }) {
return <h1>Hello, {name}!</h1>; // Hello, John Doe!
}
React Children Props
Prop'lar bir component'in açılış ve kapanış etiketleri arasına veri yerleştirerek de geçirilebilir. Bu şekilde gönderilen proplar children prop olarak adlandırılır ve JSX’i iç içe koyarak diğer bileşenlere geçirmenizi sağlar:
function App() {
return (
<User>
<h1>Hello, John Doe!</h1>
</User>
);
}
function User({ children }) {
return children; //<h1>Hello, John Doe!</h1>
: Hello, John Doe!
}
React Conditionals
React'ta jsx içerisinde if koşulu kullanılmaz bunun yerine üçlü(ternary) operatörü kullanırız.
function App() {
const isAuthUser = useAuth();
return (
<>
<h1>My App</h1>
{isAuthUser ? <AuthApp /> : <UnAuthApp />}
</>
)
}
React Lists
.map() fonksiyonu
.map(), veri dizileri üzerinde döngü oluşturmamıza ve JSX çıktısı almamıza olanak tanır.
function SoccerPlayers() {
const players = ["Messi", "Ronaldo", "Laspada"];
return (
<div>
{players.map((playerName) => (
<SoccerPlayer key={playerName} name={playerName} />
))}
</div>
);
}
Bir listeyi jsx içerisinde döndüğünüzde ona benzersiz(unique) bir key değeri eklemeyi unutmayın. Key değerleri yalnızca kardeşler arasında benzersiz olmalıdır.
React Context
React context, verileri prop kullanmadan component ağacımıza aktarmamızı sağlar.
Proplarla ilgili sorun, bazen onları alması gerekmeyen componentlerden geçirmemizdir. Bu soruna props drilling
denir.
Aşağıdaki örnekte Body componentine (body componenti bu prop'u kullanmadığı halde) alt bileşeni olan Greeting komponentine iletmesi için prop geçirilmiştir.
function App() {
return (
<Body name="John Doe" />
);
}
function Body({ name }) {
return (
<Greeting name={name} />
);
}
function Greeting({ name }) {
return <h1>Welcome, {name}</h1>;
}
Context'i kullanmak için React'tan createContext fonksiyonunu kullanırız.
Context'i, context içine konulacak bir initial value ile ayarlarız.
Oluşturulan context, bir Provider
ve Consumer
propertisi içerir. (Provider ve Consumer birer componenttir)
Provider'ı verilen değeri iletmek istediğimiz component ağacının etrafına sararız. Ardından Comsumer'ı değeri tüketmek istediğimiz component'e yerleştiririz.
import { createContext } from 'react';
const NameContext = createContext('');
function App() {
return (
<NameContext.Provider value="John Doe">
<Body />
<NameContext.Provider>
);
}
function Body() {
return <Greeting />;
}
function Greeting() {
return (
<NameContext.Consumer>
{name => <h1>Welcome, {name}</h1>}
</NameContext.Consumer>
);
}
React Hooks
Fonksiyon component'lere durum bilgisi eklemenin kolay bir yolunu sunar.
Mevcut hookları kullanabilir ya da uygulamanıza özel işlev sağlamak istiyorsanız özel hooklarınızı yazabilirsiniz.
Hook’lar class’ların içerisinde çalışmazlar ve React’ı class’lar olmadan kullanmanıza yararlar.
✌️ Hook’ların Kuralları
Hook’ları her zaman React fonksiyonunuzun en üst seviyesinde, herhangi bir return yapmadan önce kullanın. Bu kuralı uygulayarak, bir bileşenin her render edildiğinde Hook‘ların aynı sırada çağrıldığından emin olursunuz. React’in çoklu useState ve useEffect çağrıları arasındaki Hook’ların durumunu doğru şekilde korumasını sağlayan şey budur.
Hook’ları döngülerin, koşulların veya iç içe fonksiyonların içerisinde çağırmayın.
Hook’ları sadece fonksiyonel React bileşenlerinde çağırın. Normal JavaScript fonksiyonları içerisinde Hook’ları çağırmayın.
⚡️useState Hook’u
useState
fonksiyon component'lerde durum bilgisi olan(stateful) değerler kullanmanıza olanak sağlar.
import { useState } from 'react';
function MyComponent() {
const [stateValue, setStateValue] = useState(initialValue);
}
useState kullanmanın temel bir örneği, bir sayacı artırmaktır.
Count değişkeninden o anki sayımı görebilir ve setCount işlevine count + 1 geçirerek durumu artırabiliriz.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function updateCount() {
setCount(count + 1);
}
return <button onClick={updateCount}>Count is: {count}</button>;
}
State'i fonksiyondan başlatmak
const StateFromFn = () => {
const [token] = useState(() => {
let token = window.localStorage.getItem("my-token");
return token || "default#-token#"
})
return <div>Token is {token}</div>
}
State'in bir önceki değeri prevState
const CounterFnSetState = () => {
const [count, setCount] = useState(0);
return (
<>
<p>Count value is: {count}</p>
<button onClick={() => setCount(0)}>Reset</button>
<button
onClick={() => setCount(prevCount => prevCount + 1)}>
Plus (+)
</button>
<button
onClick={() => setCount(prevCount => prevCount - 1)}>
Minus (-)
</button>
</>
);
}
⚡️useEffect Hook’u
Bir API kullanmak gibi dış dünya ile etkileşim kurmak istiyorsak useEffect hook'unu kullanırız.
useEffect, bir yan etki (side effect) gerçekleştirmek için kullanılır; bu, uygulamamızın dışında var olan ve öngörülebilir bir sonucu olmayan bir işlemi gerçekleştirmek anlamına gelir.
React effect’leri her render sonrasında çalıştırır. İlk render da buna dahildir.
import { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
// perform side effect here
}, []);
}
Veri almak istiyorsak, bir gönderi listesini almak ve görüntülemek gibi useEffect'i kullanırız:
import { useEffect } from 'react';
function PostList() {
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(posts => setPosts(posts));
}, []);
return posts.map(post => <Post key={post.id} post={post} />
}
Efekt fonksiyonunun dışından gelen bir değer kullanmamız gerekiyorsa, bu, bağımlılıklar dizisine dahil edilmelidir.
Örneğin, mobile menu her açıldığında veya kapatıldığında body elementine "overflow-hidden" sınıfını ekleyen veya kaldıran bir kod parçası.
function Mobile({ open }) {
useEffect(() => {
const body = document.querySelector("#__next");
if (open) {
body.classList.add("overflow-hidden");
} else {
body.classList.remove("overflow-hidden");
}
}, [open]);
}
Efektleri Atlayarak Performansı Optimize Etme
Yeniden render olması arasında belirli değerler değişmediyse React’e bir efekti uygulamayı atlamasını söyleyebilirsiniz. Bunu yapmak için, bir diziyi useEffect e isteğe bağlı ikinci bir parametre olarak iletin:
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes
Yukarıdaki örnekte, ikinci argüman olarak [count] u iletiyoruz. Bunun anlamı count eğer 5 ise ve daha sonra bileşenimiz count hala 5 e eşit olacak şekilde yeniden oluşturulursa, React önceki render daki [5] ile sonraki render daki [5] ‘i karşılaştırır. Dizideki tüm öğeler aynı olduğundan (5 === 5), React efekti atlar.
Bir efekt çalıştırmak ve yalnızca bir kez temizlemek istiyorsanız (mount ve unmount sırasında), boş bir diziyi ([]) ikinci argüman olarak iletebilirsiniz. Bu, React’e efektinizin props veya state’deki hiçbir değere bağlı olmadığını, bu yüzden asla yeniden çalıştırılması gerekmediğini söyler.
Skipping effects (boş dependency dizisi)
Efekt yanlızca mount sırasında çağrılır. (Componentin ilk render olması durumunda)
useEffect(() => {
document.title = `New value: ${value}`
},[])
Skipping effects (Bağımlılık (dependency dizisi kullanmadan))
Bu durumda fonksiyon her render işleminden sonra yeniden çağrılır. Örneğin state her güncellendiğinde useEffect fonksiyonu da çalışır.
useEffect(() => {
console.log(“This will be logged after every render!”)
})
Conditional useEffect
Eğer bir efekti koşullu olarak çalıştırmak istiyorsak, bu koşulu Hook’umuzun içerisine koyabiliriz:
useEffect(() => {
if (value > 0) {
document.title = `New value: ${value}`
}
})
useEffect cleanup function
Bir bileşen kaldırıldığında ya da yok edildiğinde kodu yürütmek için useEffect fonksiyonuna bir 'return' ifadesi eklemeniz gerekir.
useEffect(() => {
const timer = window.setInterval(() => {
setCount(count => count + 1)
}, 1000)
return () => clearInterval(timer)
}, [])
'clearInterval(timer)' kodu, yalnızca component kullanıcı arabiriminden kaldırılmadanönce yürütülür.
başka bir örnek:
const EffectCleanup = () => {
useEffect(() => {
const clicked = () => console.log('window clicked')
window.addEventListener('click', clicked)
// return a clean-up function
return () => {
window.removeEventListener('click', clicked)
}
}, [])
return <div>
When you click the window you'll
find a message logged to the console
</div>
}
Çoklu satır içi if
<span className={count === 0 && 'text-gray-500' || count > 0 && 'text-green-500' || count < 0 && 'text-red-500'}>{count}</span>
⚡️useRef Hook’u
useRef
, bir JSX öğesine doğrudan erişmemizi sağlar.
useRef çoğunlukla bir DOM öğesini hedeflemek için kullanılır. Ancak, her oluşturma arasında değişen bir değeri korumak için de kullanılır. useRef useState gibi re-render'ı (yeniden oluşturmayı) tetiklemez.
import { useRef } from 'react';
function MyComponent() {
const ref = useRef();
return <div ref={ref} />
}
Bir elemente ref eklendiğinde, elementin kendisine erişmek için ref.current
üzerinde depolanan değeri kullanabiliriz.
örneğin kullanıcılar Control + K tuş bileşimini kullandıklarında search imputuna odaklanan bir kod yazmak istersek:
import { useWindowEvent } from "@mantine/hooks";
import { useRef } from "react";
function Header() {
const inputRef = useRef();
useWindowEvent("keydown", (event) => {
if (event.code === "KeyK" && event.ctrlKey) {
event.preventDefault();
inputRef.current.focus();
}
});
return <input ref={inputRef} />
}
Diğer bir örnek:
const UseRefBasics = () => {
const refContainer = useRef(null)
const handleSubmit = (e) => {
e.preventDefault()
console.log(refContainer.current.value)
}
useEffect(() => {
refContainer.current.focus()
}, [])
return (
<div>
<form className="form" onSubmit={handleSubmit}>
<div>
<input ref={refContainer} type="text" />
<button type="submit">Submit</button>
</div>
</form>
</div>
)
};
⚡️useContext Hook’u
useContext, standart Context.Consumer bileşenini kullanmaktan daha kolay bir context tüketme yolu sağlar.
Sözdizimi, tüketmek istediğimiz tüm Context nesnesini useContext'e geçirmeyi içerir. Döndürülen değer, Context'e aktarılan değerdir.
import { useContext } from 'react';
function MyComponent() {
const value = useContext(Context);
}
Daha önceki örneğimizi useContext hook'unu kullanarak yeniden yazmak için:
import { createContext, useContext } from 'react';
const NameContext = createContext('');
function App() {
return (
<NameContext.Provider value="John Doe">
<Body />
</NameContext.Provider>
);
}
function Body() {
return <Greeting />;
}
function Greeting() {
const name = useContext(NameContext);
return (
<h1>Welcome, {name}</h1>
);
}
Not: oluşturduğunuz context'i farklı bir sayfadan çağırmak için const anahtar sözcüğünün başına export eklemeyi unutmayın! :)
örnek: export const name = useContext(NameContext);
Bir diğer örnek:
// example Context object
const ThemeContext = React.createContext("dark");
// usage with context Consumer
function Button() {
return <ThemeContext.Consumer>
{theme => <button className={theme}> Amazing button </button>}
</ThemeContext.Consumer>
}
// usage with useContext hook
import {useContext} from 'react';
function ButtonHooks() {
const theme = useContext(ThemeContext)
return <button className={theme}>Amazing button</button>
}
Değeri kullanmak için:
const ThemeContext = React.createContext('light');
const Display = () => {
const theme = useContext(ThemeContext);
return <div
style={{
background: theme === 'dark' ? 'black' : 'papayawhip',
color: theme === 'dark' ? 'white' : 'palevioletred',
width: '100%',
minHeight: '200px'
}}
>
{'The theme here is ' + theme}
</div>
}
⚡️useCallback Hook’u
useCallback
, uygulamamızın performansına yardımcı olmak için kullandığımız bir hook'dur.
Özellikle, uygulamamızın performansına zarar verebilecek bir component her render edildiğinde (re-renders) fonksiyonların yeniden oluşturulmasını önler.
Hook'u kullanmak için callback fonksiyonumuzu useCallback içerisine sararız ve bağımlılıklar dizisine (dependency list'e) değişmesi durumunda fonsiyonun yeniden çalıştırılacağı parametreyi ekleriz.
function App() {
const [player, setPlayer] = React.useState("");
const [players, setPlayers] = React.useState(["Messi", "Ronaldo", "Laspada"]);
function handleChangeInput(event) {
setPlayer(event.target.value);
}
function handleAddPlayer() {
setPlayers(players.concat(player));
}
const handleRemovePlayer = useCallback(player => {
setPlayers(players.filter((p) => p !== player));
}, [players])
return (
<>
<input onChange={handleChangeInput} />
<button onClick={handleAddPlayer}>Add Player</button>
<PlayerList players={players} handleRemovePlayer={handleRemovePlayer} />
</>
);
}
function PlayerList({ players, handleRemovePlayer }) {
return (
<ul>
{players.map((player) => (
<li key={player} onClick={() => handleRemovePlayer(player)}>
{player}
</li>
))}
</ul>
);
}
⚡️useMemo Hook’u
useMemo, belirli bir işlemi "not almamıza" izin veren başka bir performans hook'udur.
Memoization, pahalı hesaplamaların sonucunu, daha önce yapılmış olduklarında hatırlamayı mümkün kılar, böylece onları tekrar hesaplamak zorunda kalmayız.(Aynı değişkenlerle bir fonksiyonu çalıştırdığınızda yeniden hesaplama ve re-render yapmaz, daha önce yapılan hesaplamanın değerini kullanır.)
useEffect ve useCallback gibi, useMemo da bir callback fonksiyonunu ve bir bağımlılık dizisini (dependencies array) kabul eder.
Ancak bu fonksiyonların her ikisinden de farklı olarak useMemo'nun bir değer döndürmesi amaçlanmıştır.
Değeri ya açık olarak return keyword'ü ile ya da dolaylı(implicitly) olarak arrow function kısayolunu kullanarak döndürmelisiniz.
function App() {
const [count, setCount] = useState(10)
const expensiveComputation = useMemo(() => {
return count * 2
}, [count])
return (
<>
<p>Count: {count}</p>
<p>Expensive count: {expensiveComputation}</p>
<button onClick={() => setCount(count + 1)}>Increment count</button>
</>
)
}
Gerçek dünyadan bir useMemo örneği, mdx-bundler belgelerinden gelir. mdx-bundler, .mdx dosyalarını React component'lerine dönüştürmek için bir kitaplıktır.
Burada, ham bir kod dizisini bir React component'ine dönüştürmek için useMemo kullanır.
import * as React from 'react'
import {getMDXComponent} from 'mdx-bundler/client'
function Post({code, frontmatter}) {
const Component = React.useMemo(() => getMDXComponent(code), [code]);
return (
<>
<header>
<h1>{frontmatter.title}</h1>
<p>{frontmatter.description}</p>
</header>
<main>
<Component />
</main>
</>
)
}
Bunu yapmanın nedeni, component yeniden oluşturulduğunda component değerinin gereksiz yere yeniden oluşturulmasını önlemektir.
useMemo bu nedenle yalnızca kod bağımlılığı değişirse callback fonksiyonunu yürütür.
Aşağıdaki örnekte someValue nesnesi useMemo kulllanılarak not alınabilir. Ve bu böylece gereksiz re-render işlemi gerçekleşmez.
const App = () => {
const [age, setAge] = useState(99)
const handleClick = () => setAge(age + 1)
const someValue = useMemo(() => ({ value: "someValue" }))
const doSomething = () => {
return someValue
}
return (
<div>
<Age age={age} handleClick={handleClick}/>
<Instructions doSomething={doSomething} />
</div>
)
}
const Age = ({ age, handleClick }) => {
return (
<div>
<div style={{ border: '2px', background: "papayawhip", padding: "1rem" }}>
Today I am {age} Years of Age
</div>
<pre> - click the button below 👇 </pre>
<button onClick={handleClick}>Get older! </button>
</div>
)
}
const Instructions = React.memo((props) => {
return (
<div style={{ background: 'black', color: 'yellow', padding: "1rem" }}>
<p>Follow the instructions above as closely as possible</p>
</div>
)
})
ReactDOM.render (<App />)
⚡️useLayoutEffect Hook’u
useEffect ile benzer bir kullanıma sahiptir ancak useEffect'e geçirilen fonksiyon, render ekrana işlendikten sonra etkinleşir.
Bu, tarayıcının ekranı güncellemesini engellememesi gereken çoğu yan etki(side effects) için uygundur. Yine de useEffect'in sağladığı davranışı istemeyebileceğiniz durumlar vardır; örneğin, side effect olarak DOM'da görsel bir değişiklik yapmanız gerekiyorsa, useEffect en iyi seçim olmayacaktır.
Kullanıcının değişiklik titreşimlerini görmesini önlemek için useLayoutEffect'i kullanabilirsiniz. useLayoutEffect'e geçirilen fonksiyon, tarayıcı ekranı güncellemeden önce çalıştırılacaktır.
const ArrayDep = () => {
const [randomNumber, setRandomNumber] = useState(0)
const [effectLogs, setEffectLogs] = useState([])
useLayoutEffect(
() => {
setEffectLogs(prevEffectLogs => [...prevEffectLogs, 'effect fn has been invoked'])
},
[randomNumber]
)
return (
<div>
<h1>{randomNumber}</h1>
<button
onClick={() => {
setRandomNumber(Math.random())
}}
>
Generate random number!
</button>
<div>
{effectLogs.map((effect, index) => (
<div key={index}>{'🍔'.repeat(index) + effect}</div>
))}
</div>
</div>
)
}
⚡️useReducer Hook’u
useReducer Hook'u, useState Hook'unun bir alternatifi olarak düşünülebilir ve daha kapsamlı state yönetimi için kullanılabilir. Özellikle çok sayıda state değişkeni veya state değişkenleri arasındaki bağımlılıklar varsa, useReducer Hook'u daha uygun olabilir. previous (önceki) state değerine veya birçok state alt değerine (sub-values) bağımlılığın olduğu complex state mantığı için idealdir.
const initialState = { width: 15 };
const reducer = (state, action) => {
switch (action) {
case 'plus':
return { width: state.width + 15 }
case 'minus':
return { width: Math.max(state.width - 15, 2) }
default:
throw new Error("what's going on?" )
}
}
const Bar = () => {
const [state, dispatch] = useReducer(reducer, initialState)
return <>
<div style={{ background: 'teal', height: '30px', width: state.width }}></div>
<div style={{marginTop: '3rem'}}>
<button onClick={() => dispatch('plus')}>Increase bar size</button>
<button onClick={() => dispatch('minus')}>Decrease bar size</button>
</div>
</>
}
ReactDOM.render(<Bar />)
Initialize state lazily
useReducer üçüncü bir fonksiyon parametresi alır. Bu fonksiyondan state'i başlatabilirsiniz ve bu fonksiyondan ne döndürülürse state nesnesi olarak döndürülür.
const initializeState = () => ({
width: 100
})
const initialState = { width: 15 }
const reducer = (state, action) => {
switch (action) {
case 'plus':
return { width: state.width + 15 }
case 'minus':
return { width: Math.max(state.width - 15, 2) }
default:
throw new Error("what's going on?" )
}
}
const Bar = () => {
const [state, dispatch] = useReducer(reducer, initialState, initializeState)
return <>
<div style={{ background: 'teal', height: '30px', width: state.width }}></div>
<div style={{marginTop: '3rem'}}>
<button onClick={() => dispatch('plus')}>Increase bar size</button>
<button onClick={() => dispatch('minus')}>Decrease bar size</button>
</div>
</>
}
ReactDOM.render(Bar)
e.preventDefault()
React'ta bir elementin varsayılan davranışını engellemek için e.preventDefault() kullanılır.
Örnek: Formun onSubmit olayını engellemek için:
function Form() {
function handleSubmit(e) {
e.preventDefault();
console.log('You clicked submit.');
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}
React.lazy
React.lazy fonksiyonu, dinamik import’u normal bir bileşen gibi render etmeye yarar.
const OtherComponent = React.lazy(() => import('./OtherComponent'));
Suspense
Suspense, componentlerin render edilmeden önce bir şey için “beklemesini” sağlar. Şu an için, Suspense yalnızca bir kullanım durumunu destekler: : componentleri React.lazy ile dinamik olarak yükleme.
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
//fallback prop’u, bileşenin
yüklenmesini beklerken göstermek
istediğiniz herhangi bir React elemanını
kabul eder.
<Suspense fallback={<div>Yükleniyor...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
Transitions
Transitions, Güncellemeleri transitions olarak işaretlemenize olanak tanır, bu da React'e kesintiye uğrayabileceklerini söyler ve zaten görünür olan içerik için Suspense yedeklerine geri dönmekten kaçınır.
useTransition
const [isPending, startTransition] = useTransition();
Geçişin bekleyen(pending) state'i için stateful value ve bunu başlatmak için bir fonksiyon döndürür.
startTransition, sağlanan callback deki güncellemeleri transitions(geçişler) olarak işaretlemenizi sağlar:
startTransition(() => {
setCount(count + 1);
})
isPending, bekleyen bir durumu(pending state) göstermek için bir transition'ın ne zaman etkin olduğunu gösterir:
function App() {
const [isPending, startTransition] = useTransition();
const [count, setCount] = useState(0);
function handleClick() {
startTransition(() => {
setCount(c => c + 1);
})
}
return (
<div>
{isPending && <Spinner />}
<button onClick={handleClick}>{count}</button>
</div>
);
}
Default Props value
const Person = ({name, age, children}) => {
return (
<h1>Name: {name} Age: {age}</h1>
<p>{children}</p>
)
}
Person.defaultProps = {
name: 'No name',
age: 0,
}
Props object destructuring
function App(){
return people.map(person => <Person key={person.id} {...person} />)
}
const Person = ({name, age}) => {
return (
<h1>Name: {name}, Age: {age}</h1>
)
}
Güncellenmeye devam edecek...
Kaynaklar :)
- https://tr.reactjs.org/docs/introducing-jsx.html
- https://www.freecodecamp.org/news/the-react-cheatsheet/
- https://medium.com/coinmonks/react-js-cheatsheet-for-beginners-5665425d9026
- https://stackoverflow.com/questions/65823965/react-context-is-not-defined-no-undef/65824439#65824439
- https://dev.to/ericchapman/react-cheat-sheet-updated-may-2021-1mcd
- https://codingcheats.io/react/
- https://blog.logrocket.com/react-hooks-cheat-sheet-unlock-solutions-to-common-problems-af4caf699e70/
Top comments (0)