From 1c84cfd32b0f63c2e80550eb21e2573ff1040293 Mon Sep 17 00:00:00 2001 From: Wralith Date: Mon, 17 Oct 2022 16:42:33 +0300 Subject: [PATCH 01/17] Create tr folder Copy en folder content --- langs/tr/api/api.md | 2388 +++++++++++++++++ langs/tr/guides/comparison.md | 77 + langs/tr/guides/directory.json | 42 + langs/tr/guides/faq.md | 132 + langs/tr/guides/getting-started.md | 170 ++ langs/tr/guides/reactivity.md | 95 + langs/tr/guides/rendering.md | 282 ++ langs/tr/guides/server.md | 140 + langs/tr/guides/testing.md | 431 +++ langs/tr/guides/typescript.md | 632 +++++ langs/tr/tutorials/async_lazy/lesson.json | 12 + langs/tr/tutorials/async_lazy/lesson.md | 20 + langs/tr/tutorials/async_lazy/solved.json | 12 + .../tr/tutorials/async_resources/lesson.json | 8 + langs/tr/tutorials/async_resources/lesson.md | 19 + .../tr/tutorials/async_resources/solved.json | 8 + langs/tr/tutorials/async_suspense/lesson.json | 12 + langs/tr/tutorials/async_suspense/lesson.md | 31 + langs/tr/tutorials/async_suspense/solved.json | 12 + .../tutorials/async_suspense_list/lesson.json | 16 + .../tutorials/async_suspense_list/lesson.md | 17 + .../tutorials/async_suspense_list/solved.json | 16 + .../tutorials/async_transitions/lesson.json | 17 + .../tr/tutorials/async_transitions/lesson.md | 22 + .../tutorials/async_transitions/solved.json | 17 + .../tutorials/bindings_classlist/lesson.json | 13 + .../tr/tutorials/bindings_classlist/lesson.md | 27 + .../tutorials/bindings_classlist/solved.json | 13 + .../tutorials/bindings_directives/lesson.json | 17 + .../tutorials/bindings_directives/lesson.md | 26 + .../tutorials/bindings_directives/solved.json | 17 + .../tr/tutorials/bindings_events/lesson.json | 13 + langs/tr/tutorials/bindings_events/lesson.md | 22 + .../tr/tutorials/bindings_events/solved.json | 13 + .../bindings_forward_refs/lesson.json | 17 + .../tutorials/bindings_forward_refs/lesson.md | 9 + .../bindings_forward_refs/solved.json | 17 + langs/tr/tutorials/bindings_refs/lesson.json | 13 + langs/tr/tutorials/bindings_refs/lesson.md | 27 + langs/tr/tutorials/bindings_refs/solved.json | 13 + .../tr/tutorials/bindings_spreads/lesson.json | 12 + langs/tr/tutorials/bindings_spreads/lesson.md | 9 + .../tr/tutorials/bindings_spreads/solved.json | 12 + langs/tr/tutorials/bindings_style/lesson.json | 8 + langs/tr/tutorials/bindings_style/lesson.md | 20 + langs/tr/tutorials/bindings_style/solved.json | 8 + langs/tr/tutorials/directory.json | 162 ++ langs/tr/tutorials/flow_dynamic/lesson.json | 8 + langs/tr/tutorials/flow_dynamic/lesson.md | 18 + langs/tr/tutorials/flow_dynamic/solved.json | 8 + .../tutorials/flow_error_boundary/lesson.json | 8 + .../tutorials/flow_error_boundary/lesson.md | 9 + .../tutorials/flow_error_boundary/solved.json | 8 + langs/tr/tutorials/flow_for/lesson.json | 8 + langs/tr/tutorials/flow_for/lesson.md | 19 + langs/tr/tutorials/flow_for/solved.json | 8 + langs/tr/tutorials/flow_index/lesson.json | 8 + langs/tr/tutorials/flow_index/lesson.md | 21 + langs/tr/tutorials/flow_index/solved.json | 8 + langs/tr/tutorials/flow_portal/lesson.json | 13 + langs/tr/tutorials/flow_portal/lesson.md | 14 + langs/tr/tutorials/flow_portal/solved.json | 13 + langs/tr/tutorials/flow_show/lesson.json | 8 + langs/tr/tutorials/flow_show/lesson.md | 16 + langs/tr/tutorials/flow_show/solved.json | 8 + langs/tr/tutorials/flow_switch/lesson.json | 8 + langs/tr/tutorials/flow_switch/lesson.md | 16 + langs/tr/tutorials/flow_switch/solved.json | 8 + .../tutorials/introduction_basics/lesson.json | 8 + .../tutorials/introduction_basics/lesson.md | 29 + .../tutorials/introduction_basics/solved.json | 8 + .../introduction_components/lesson.json | 12 + .../introduction_components/lesson.md | 24 + .../introduction_components/solved.json | 12 + .../introduction_derived/lesson.json | 8 + .../tutorials/introduction_derived/lesson.md | 16 + .../introduction_derived/solved.json | 8 + .../introduction_effects/lesson.json | 8 + .../tutorials/introduction_effects/lesson.md | 21 + .../introduction_effects/solved.json | 8 + .../tr/tutorials/introduction_jsx/lesson.json | 8 + langs/tr/tutorials/introduction_jsx/lesson.md | 31 + .../tr/tutorials/introduction_jsx/solved.json | 8 + .../tutorials/introduction_memos/lesson.json | 8 + .../tr/tutorials/introduction_memos/lesson.md | 16 + .../tutorials/introduction_memos/solved.json | 8 + .../introduction_signals/lesson.json | 8 + .../tutorials/introduction_signals/lesson.md | 29 + .../introduction_signals/solved.json | 8 + .../lifecycles_oncleanup/lesson.json | 8 + .../tutorials/lifecycles_oncleanup/lesson.md | 10 + .../lifecycles_oncleanup/solved.json | 8 + .../tutorials/lifecycles_onmount/lesson.json | 13 + .../tr/tutorials/lifecycles_onmount/lesson.md | 16 + .../tutorials/lifecycles_onmount/solved.json | 13 + langs/tr/tutorials/props_children/lesson.json | 12 + langs/tr/tutorials/props_children/lesson.md | 33 + langs/tr/tutorials/props_children/solved.json | 12 + langs/tr/tutorials/props_defaults/lesson.json | 12 + langs/tr/tutorials/props_defaults/lesson.md | 13 + langs/tr/tutorials/props_defaults/solved.json | 12 + langs/tr/tutorials/props_split/lesson.json | 12 + langs/tr/tutorials/props_split/lesson.md | 26 + langs/tr/tutorials/props_split/solved.json | 12 + .../tr/tutorials/reactivity_batch/lesson.json | 8 + langs/tr/tutorials/reactivity_batch/lesson.md | 16 + .../tr/tutorials/reactivity_batch/solved.json | 8 + langs/tr/tutorials/reactivity_on/lesson.json | 8 + langs/tr/tutorials/reactivity_on/lesson.md | 9 + langs/tr/tutorials/reactivity_on/solved.json | 8 + .../tutorials/reactivity_untrack/lesson.json | 8 + .../tr/tutorials/reactivity_untrack/lesson.md | 12 + .../tutorials/reactivity_untrack/solved.json | 8 + langs/tr/tutorials/stores_context/lesson.json | 16 + langs/tr/tutorials/stores_context/lesson.md | 28 + langs/tr/tutorials/stores_context/solved.json | 16 + .../tutorials/stores_createstore/lesson.json | 8 + .../tr/tutorials/stores_createstore/lesson.md | 29 + .../tutorials/stores_createstore/solved.json | 8 + .../tr/tutorials/stores_immutable/lesson.json | 20 + langs/tr/tutorials/stores_immutable/lesson.md | 43 + .../tr/tutorials/stores_immutable/solved.json | 20 + .../tr/tutorials/stores_mutation/lesson.json | 8 + langs/tr/tutorials/stores_mutation/lesson.md | 23 + .../tr/tutorials/stores_mutation/solved.json | 8 + .../stores_nested_reactivity/lesson.json | 8 + .../stores_nested_reactivity/lesson.md | 32 + .../stores_nested_reactivity/solved.json | 8 + .../tr/tutorials/stores_nocontext/lesson.json | 12 + langs/tr/tutorials/stores_nocontext/lesson.md | 31 + .../tr/tutorials/stores_nocontext/solved.json | 12 + 131 files changed, 6264 insertions(+) create mode 100644 langs/tr/api/api.md create mode 100644 langs/tr/guides/comparison.md create mode 100644 langs/tr/guides/directory.json create mode 100644 langs/tr/guides/faq.md create mode 100644 langs/tr/guides/getting-started.md create mode 100644 langs/tr/guides/reactivity.md create mode 100644 langs/tr/guides/rendering.md create mode 100644 langs/tr/guides/server.md create mode 100644 langs/tr/guides/testing.md create mode 100644 langs/tr/guides/typescript.md create mode 100644 langs/tr/tutorials/async_lazy/lesson.json create mode 100644 langs/tr/tutorials/async_lazy/lesson.md create mode 100644 langs/tr/tutorials/async_lazy/solved.json create mode 100644 langs/tr/tutorials/async_resources/lesson.json create mode 100644 langs/tr/tutorials/async_resources/lesson.md create mode 100644 langs/tr/tutorials/async_resources/solved.json create mode 100644 langs/tr/tutorials/async_suspense/lesson.json create mode 100644 langs/tr/tutorials/async_suspense/lesson.md create mode 100644 langs/tr/tutorials/async_suspense/solved.json create mode 100644 langs/tr/tutorials/async_suspense_list/lesson.json create mode 100644 langs/tr/tutorials/async_suspense_list/lesson.md create mode 100644 langs/tr/tutorials/async_suspense_list/solved.json create mode 100644 langs/tr/tutorials/async_transitions/lesson.json create mode 100644 langs/tr/tutorials/async_transitions/lesson.md create mode 100644 langs/tr/tutorials/async_transitions/solved.json create mode 100644 langs/tr/tutorials/bindings_classlist/lesson.json create mode 100644 langs/tr/tutorials/bindings_classlist/lesson.md create mode 100644 langs/tr/tutorials/bindings_classlist/solved.json create mode 100644 langs/tr/tutorials/bindings_directives/lesson.json create mode 100644 langs/tr/tutorials/bindings_directives/lesson.md create mode 100644 langs/tr/tutorials/bindings_directives/solved.json create mode 100644 langs/tr/tutorials/bindings_events/lesson.json create mode 100644 langs/tr/tutorials/bindings_events/lesson.md create mode 100644 langs/tr/tutorials/bindings_events/solved.json create mode 100644 langs/tr/tutorials/bindings_forward_refs/lesson.json create mode 100644 langs/tr/tutorials/bindings_forward_refs/lesson.md create mode 100644 langs/tr/tutorials/bindings_forward_refs/solved.json create mode 100644 langs/tr/tutorials/bindings_refs/lesson.json create mode 100644 langs/tr/tutorials/bindings_refs/lesson.md create mode 100644 langs/tr/tutorials/bindings_refs/solved.json create mode 100644 langs/tr/tutorials/bindings_spreads/lesson.json create mode 100644 langs/tr/tutorials/bindings_spreads/lesson.md create mode 100644 langs/tr/tutorials/bindings_spreads/solved.json create mode 100644 langs/tr/tutorials/bindings_style/lesson.json create mode 100644 langs/tr/tutorials/bindings_style/lesson.md create mode 100644 langs/tr/tutorials/bindings_style/solved.json create mode 100644 langs/tr/tutorials/directory.json create mode 100644 langs/tr/tutorials/flow_dynamic/lesson.json create mode 100644 langs/tr/tutorials/flow_dynamic/lesson.md create mode 100644 langs/tr/tutorials/flow_dynamic/solved.json create mode 100644 langs/tr/tutorials/flow_error_boundary/lesson.json create mode 100644 langs/tr/tutorials/flow_error_boundary/lesson.md create mode 100644 langs/tr/tutorials/flow_error_boundary/solved.json create mode 100644 langs/tr/tutorials/flow_for/lesson.json create mode 100644 langs/tr/tutorials/flow_for/lesson.md create mode 100644 langs/tr/tutorials/flow_for/solved.json create mode 100644 langs/tr/tutorials/flow_index/lesson.json create mode 100644 langs/tr/tutorials/flow_index/lesson.md create mode 100644 langs/tr/tutorials/flow_index/solved.json create mode 100644 langs/tr/tutorials/flow_portal/lesson.json create mode 100644 langs/tr/tutorials/flow_portal/lesson.md create mode 100644 langs/tr/tutorials/flow_portal/solved.json create mode 100644 langs/tr/tutorials/flow_show/lesson.json create mode 100644 langs/tr/tutorials/flow_show/lesson.md create mode 100644 langs/tr/tutorials/flow_show/solved.json create mode 100644 langs/tr/tutorials/flow_switch/lesson.json create mode 100644 langs/tr/tutorials/flow_switch/lesson.md create mode 100644 langs/tr/tutorials/flow_switch/solved.json create mode 100644 langs/tr/tutorials/introduction_basics/lesson.json create mode 100644 langs/tr/tutorials/introduction_basics/lesson.md create mode 100644 langs/tr/tutorials/introduction_basics/solved.json create mode 100644 langs/tr/tutorials/introduction_components/lesson.json create mode 100644 langs/tr/tutorials/introduction_components/lesson.md create mode 100644 langs/tr/tutorials/introduction_components/solved.json create mode 100644 langs/tr/tutorials/introduction_derived/lesson.json create mode 100644 langs/tr/tutorials/introduction_derived/lesson.md create mode 100644 langs/tr/tutorials/introduction_derived/solved.json create mode 100644 langs/tr/tutorials/introduction_effects/lesson.json create mode 100644 langs/tr/tutorials/introduction_effects/lesson.md create mode 100644 langs/tr/tutorials/introduction_effects/solved.json create mode 100644 langs/tr/tutorials/introduction_jsx/lesson.json create mode 100644 langs/tr/tutorials/introduction_jsx/lesson.md create mode 100644 langs/tr/tutorials/introduction_jsx/solved.json create mode 100644 langs/tr/tutorials/introduction_memos/lesson.json create mode 100644 langs/tr/tutorials/introduction_memos/lesson.md create mode 100644 langs/tr/tutorials/introduction_memos/solved.json create mode 100644 langs/tr/tutorials/introduction_signals/lesson.json create mode 100644 langs/tr/tutorials/introduction_signals/lesson.md create mode 100644 langs/tr/tutorials/introduction_signals/solved.json create mode 100644 langs/tr/tutorials/lifecycles_oncleanup/lesson.json create mode 100644 langs/tr/tutorials/lifecycles_oncleanup/lesson.md create mode 100644 langs/tr/tutorials/lifecycles_oncleanup/solved.json create mode 100644 langs/tr/tutorials/lifecycles_onmount/lesson.json create mode 100644 langs/tr/tutorials/lifecycles_onmount/lesson.md create mode 100644 langs/tr/tutorials/lifecycles_onmount/solved.json create mode 100644 langs/tr/tutorials/props_children/lesson.json create mode 100644 langs/tr/tutorials/props_children/lesson.md create mode 100644 langs/tr/tutorials/props_children/solved.json create mode 100644 langs/tr/tutorials/props_defaults/lesson.json create mode 100644 langs/tr/tutorials/props_defaults/lesson.md create mode 100644 langs/tr/tutorials/props_defaults/solved.json create mode 100644 langs/tr/tutorials/props_split/lesson.json create mode 100644 langs/tr/tutorials/props_split/lesson.md create mode 100644 langs/tr/tutorials/props_split/solved.json create mode 100644 langs/tr/tutorials/reactivity_batch/lesson.json create mode 100644 langs/tr/tutorials/reactivity_batch/lesson.md create mode 100644 langs/tr/tutorials/reactivity_batch/solved.json create mode 100644 langs/tr/tutorials/reactivity_on/lesson.json create mode 100644 langs/tr/tutorials/reactivity_on/lesson.md create mode 100644 langs/tr/tutorials/reactivity_on/solved.json create mode 100644 langs/tr/tutorials/reactivity_untrack/lesson.json create mode 100644 langs/tr/tutorials/reactivity_untrack/lesson.md create mode 100644 langs/tr/tutorials/reactivity_untrack/solved.json create mode 100644 langs/tr/tutorials/stores_context/lesson.json create mode 100644 langs/tr/tutorials/stores_context/lesson.md create mode 100644 langs/tr/tutorials/stores_context/solved.json create mode 100644 langs/tr/tutorials/stores_createstore/lesson.json create mode 100644 langs/tr/tutorials/stores_createstore/lesson.md create mode 100644 langs/tr/tutorials/stores_createstore/solved.json create mode 100644 langs/tr/tutorials/stores_immutable/lesson.json create mode 100644 langs/tr/tutorials/stores_immutable/lesson.md create mode 100644 langs/tr/tutorials/stores_immutable/solved.json create mode 100644 langs/tr/tutorials/stores_mutation/lesson.json create mode 100644 langs/tr/tutorials/stores_mutation/lesson.md create mode 100644 langs/tr/tutorials/stores_mutation/solved.json create mode 100644 langs/tr/tutorials/stores_nested_reactivity/lesson.json create mode 100644 langs/tr/tutorials/stores_nested_reactivity/lesson.md create mode 100644 langs/tr/tutorials/stores_nested_reactivity/solved.json create mode 100644 langs/tr/tutorials/stores_nocontext/lesson.json create mode 100644 langs/tr/tutorials/stores_nocontext/lesson.md create mode 100644 langs/tr/tutorials/stores_nocontext/solved.json diff --git a/langs/tr/api/api.md b/langs/tr/api/api.md new file mode 100644 index 00000000..2cc8d00e --- /dev/null +++ b/langs/tr/api/api.md @@ -0,0 +1,2388 @@ +# Basic Reactivity + +Solid's overall approach to reactivity is to wrap any reactive computation in +a function, and rerun that function when its dependencies update. +The Solid JSX compiler also wraps most JSX expressions (code in braces) with a +function, so they automatically update (and trigger corresponding DOM updates) +when their dependencies change. +More precisely, automatic rerunning of a function happens whenever the function +gets called in a _tracking scope_, such as a JSX expression +or API calls that build "computations" (`createEffect`, `createMemo`, etc.). +By default, the dependencies of a function get tracked automatically +when they're called in a tracking scope, by detecting when the function reads +reactive state (e.g., via a Signal getter or Store attribute). +As a result, you generally don't need to worry about dependencies yourselves. +(But if automatic dependency tracking ever doesn't produce the results you +want, you can [override dependency tracking](#reactive-utilities).) +This approach makes reactivity _composable_: calling one function +within another function generally causes the calling function +to inherit the dependencies of the called function. + +## `createSignal` + +```ts +import { createSignal } from "solid-js"; + +function createSignal( + initialValue: T, + options?: { equals?: false | ((prev: T, next: T) => boolean) } +): [get: () => T, set: (v: T) => T]; + +// available types for return value of createSignal: +import type { Signal, Accessor, Setter } from "solid-js"; +type Signal = [get: Accessor, set: Setter]; +type Accessor = () => T; +type Setter = (v: T | ((prev?: T) => T)) => T; +``` + +Signals are the most basic reactive primitive. They track a single value +(which can be any JavaScript object) that changes over time. +The Signal's value starts out equal to the passed first argument +`initialValue` (or `undefined` if there are no arguments). +The `createSignal` function returns a pair of functions as a two-element array: +a _getter_ (or _accessor_) and a _setter_. In typical use, you would +destructure this array into a named Signal like so: + +```js +const [count, setCount] = createSignal(0); +const [ready, setReady] = createSignal(false); +``` + +Calling the getter (e.g., `count()` or `ready()`) +returns the current value of the Signal. +Crucial to automatic dependency tracking, calling the getter +within a tracking scope causes the calling function to depend on this Signal, +so that function will rerun if the Signal gets updated. + +Calling the setter (e.g., `setCount(nextCount)` or `setReady(nextReady)`) +sets the Signal's value and _updates_ the Signal +(triggering dependents to rerun) +if the value actually changed (see details below). +As its only argument, the setter takes either the new value for the signal, +or a function that maps the last value of the signal to a new value. +The setter also returns the updated value. For example: + +```js +// read signal's current value, and +// depend on signal if in a tracking scope +// (but nonreactive outside of a tracking scope): +const currentCount = count(); + +// or wrap any computation with a function, +// and this function can be used in a tracking scope: +const doubledCount = () => 2 * count(); + +// or build a tracking scope and depend on signal: +const countDisplay =
{count()}
; + +// write signal by providing a value: +setReady(true); + +// write signal by providing a function setter: +const newCount = setCount((prev) => prev + 1); +``` + +> If you want to store a function in a Signal you must use the function form: +> +> ```js +> setValue(() => myFunction); +> ``` +> +> However, functions are not treated specially as the `initialValue` argument +> to `createSignal`, so you should pass a function initial value as is: +> +> ```js +> const [func, setFunc] = createSignal(myFunction); +> ``` + +##### Options + +Several primitives in Solid take an "options" object +as an optional last argument. +`createSignal`'s options object allows you to provide an +`equals` option. For example: + +```js +const [getValue, setValue] = createSignal(initialValue, { equals: false }); +``` + +By default, when calling a signal's setter, the signal only updates (and causes +dependents to rerun) if the new value is actually different than the old value, +according to JavaScript's `===` operator. + +Alternatively, you can set `equals` to `false` to always rerun dependents after +the setter is called, or you can pass your own function for testing equality. +Some examples: + +```js +// use { equals: false } to allow modifying object in-place; +// normally this wouldn't be seen as an update because the +// object has the same identity before and after change +const [object, setObject] = createSignal({ count: 0 }, { equals: false }); +setObject((current) => { + current.count += 1; + current.updated = new Date(); + return current; +}); + +// use { equals: false } signal as trigger without value: +const [depend, rerun] = createSignal(undefined, { equals: false }); +// now calling depend() in a tracking scope +// makes that scope rerun whenever rerun() gets called + +// define equality based on string length: +const [myString, setMyString] = createSignal("string", { + equals: (newVal, oldVal) => newVal.length === oldVal.length, +}); + +setMyString("strung"); // considered equal to the last value and won't cause updates +setMyString("stranger"); // considered different and will cause updates +``` + +## `createEffect` + +```ts +import { createEffect } from "solid-js"; + +function createEffect(fn: (v: T) => T, value?: T): void; +``` + +Effects are a general way to make arbitrary code ("side effects") +run whenever dependencies change, e.g., to modify the DOM manually. +`createEffect` creates a new computation that runs the given function +in a tracking scope, thus automatically tracking its dependencies, +and automatically reruns the function whenever the dependencies update. +For example: + +```js +const [a, setA] = createSignal(initialValue); + +// effect that depends on signal `a` +createEffect(() => doSideEffect(a())); +``` + +The effect function gets called with an argument equal to the value returned +from the effect function's last execution, or on the first call, +equal to the optional second argument to `createEffect`. +This allows you to compute diffs without creating an additional closure +to remember the last computed value. For example: + +```js +createEffect((prev) => { + const sum = a() + b(); + if (sum !== prev) console.log("sum changed to", sum); + return sum; +}, 0); +``` + +Effects are meant primarily for side effects that read but don't write +to the reactive system: +it's best to avoid setting signals in effects, which without care +can cause additional rendering or even infinite effect loops. +Instead, prefer using [`createMemo`](#creatememo) to compute new values +that depend on other reactive values, so the reactive system knows what +depends on what, and can optimize accordingly. + +The _first_ execution of the effect function is not immediate; +it's scheduled to run after the current rendering phase +(e.g., after calling the function passed to [`render`](#render), +[`createRoot`](#createroot), or [`runWithOwner`](#runwithowner)). +If you want to wait for the first execution to occur, use +[`queueMicrotask`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask) +(which runs before the browser renders the DOM) or +`await Promise.resolve()` or `setTimeout(..., 0)` +(which run after browser rendering). + +```js +// assume this code is in a component function, so is part of a rendering phase +const [count, setCount] = createSignal(0); + +// this effect prints count at the beginning and when it changes +createEffect(() => console.log("count =", count())); +// effect won't run yet +console.log("hello"); +setCount(1); // effect still won't run yet +setCount(2); // effect still won't run yet + +queueMicrotask(() => { + // now `count = 2` will print + console.log("microtask"); + setCount(3); // immediately prints `count = 3` + console.log("goodbye"); +}); + +// --- overall output: --- +// hello +// count = 2 +// microtask +// count = 3 +// goodbye +``` + +This delay in first execution is useful because it means +an effect defined in a component scope runs after +the JSX returned by the component gets added the DOM. +In particular, [`ref`](#ref)s will already be set. +Thus you can use an effect to manipulate the DOM manually, +call vanilla JS libraries, or other side effects. + +Note that the first run of the effect still runs before the browser renders +the DOM to the screen (similar to React's `useLayoutEffect`). +If you need to wait until after rendering (e.g., to measure the rendering), +you can use `await Promise.resolve()` (or `Promise.resolve().then(...)`), +but note that subsequent use of reactive state (such as signals) +will not trigger the effect to rerun, as tracking is not +possible after an `async` function uses `await`. +Thus you should use all dependencies before the promise. + +If you'd rather an effect run immediately even for its first run, +use [`createRenderEffect`](#createrendereffect) or +[`createComputed`](#createcomputed). + +You can clean up your side effects in between executions of the effect function +by calling [`onCleanup`](#oncleanup) _inside_ the effect function. +Such a cleanup function gets called both in between effect executions and +when the effect gets disposed (e.g., the containing component unmounts). +For example: + +```js +// listen to event dynamically given by eventName signal +createEffect(() => { + const event = eventName(); + const callback = (e) => console.log(e); + ref.addEventListener(event, callback); + onCleanup(() => ref.removeEventListener(event, callback)); +}); +``` + +## `createMemo` + +```ts +import { createMemo } from "solid-js"; + +function createMemo( + fn: (v: T) => T, + value?: T, + options?: { equals?: false | ((prev: T, next: T) => boolean) } +): () => T; +``` + +Memos let you efficiently use a derived value in many reactive computations. +`createMemo` creates a readonly reactive value equal to the return value of +the given function and makes sure that function only gets executed when its dependencies change. + +```js +const value = createMemo(() => computeExpensiveValue(a(), b())); + +// read value +value(); +``` + +In Solid, you often don't need to wrap functions in memos; +you can alternatively just define and call a regular function +to get similar reactive behavior. +The main difference is when you call the function in multiple reactive settings. +In this case, when the function's dependencies update, the function will get +called multiple times unless it is wrapped in `createMemo`. For example: + +```js +const user = createMemo(() => searchForUser(username())); +// compare with: const user = () => searchForUser(username()); +return ( +
    +
  • Your name is "{user()?.name}"
  • +
  • + Your email is {user()?.email} +
  • +
+); +``` + +When the `username` signal updates, `searchForUser` will get called just once. +If the returned user actually changed, the `user` memo updates, and then both +list items will update automatically. + +If we had instead defined `user` as a plain function +`() => searchForUser(username())`, then `searchForUser` would have been +called twice, once when updating each list item. + +Another key difference is that a memo can shield dependents from updating +when the memo's dependencies change but the resulting memo value doesn't. +Like [`createSignal`](#createsignal), the derived signal made by `createMemo` +_updates_ (and triggers dependents to rerun) only when the value returned by +the memo function actually changes from the previous value, +according to JavaScript's `===` operator. +Alternatively, you can pass an options object with `equals` set to `false` +to always update the memo when its dependencies change, +or you can pass your own `equals` function for testing equality. + +The memo function gets called with an argument equal to the value returned +from the memo function's last execution, or on the first call, +equal to the optional second argument to `createMemo`. +This is useful for reducing computations, for example: + +```js +// track the sum of all values taken on by input() as it updates +const sum = createMemo((prev) => input() + prev, 0); +``` + +The memo function should not change other signals by calling setters +(it should be "pure"). +This enables Solid to optimize the execution order of memo updates +according to their dependency graph, so that all memos can update +at most once in response to a dependency change. + +## `createResource` + +```ts +import { createResource } from "solid-js"; +import type { ResourceReturn } from "solid-js"; + +type ResourceReturn = [ + { + (): T | undefined; + state: "unresolved" | "pending" | "ready" | "refreshing" | "errored" + loading: boolean; + error: any; + latest: T | undefined; + }, + { + mutate: (v: T | undefined) => T | undefined; + refetch: (info: unknown) => Promise | T; + } +]; + +export type ResourceOptions = { + initialValue?: T; + name?: string; + deferStream?: boolean; + ssrLoadFrom?: "initial" | "server"; + storage?: (init: T | undefined) => [Accessor, Setter]; + onHydrated?: (k: S | undefined, info: { value: T | undefined }) => void; +}; + +function createResource( + fetcher: ( + k: U, + info: { value: T | undefined; refetching: boolean | unknown } + ) => T | Promise, + options?: ResourceOptions +): ResourceReturn; + +function createResource( + source: U | false | null | (() => U | false | null), + fetcher: ( + k: U, + info: { value: T | undefined; refetching: boolean | unknown } + ) => T | Promise, + options?: ResourceOptions +): ResourceReturn; +``` + +Creates a signal that reflects the result of an async request. + +`createResource` takes an asynchronous fetcher function and returns a signal that is updated with the resulting data when the fetcher completes. + +There are two ways to use `createResource`: you can pass the fetcher function as the sole argument, or you can additionally pass a source signal as the first argument. The source signal will retrigger the fetcher whenever it changes, and its value will be passed to the fetcher. + +```js +const [data, { mutate, refetch }] = createResource(fetchData); +``` + +```js +const [data, { mutate, refetch }] = createResource(sourceSignal, fetchData); +``` + +In these snippets, the fetcher is the function `fetchData`, and `data()` is undefined until `fetchData` finishes resolving. In the first case, `fetchData` will be called immediately. +In the second, `fetchData` will be called as soon as `sourceSignal` has any value other than `false`, `null`, or `undefined`. +It will be called again whenever the value of `sourceSignal` changes, and that value will always be passed to `fetchData` as its first argument. + +You can call `mutate` to directly update the `data` signal (it works like any other signal setter). You can also call `refetch` to rerun the fetcher directly, and pass an optional argument to provide additional info to the fetcher: `refetch(info)`. + +`data` works like a normal signal getter: use `data()` to read the last returned value of `fetchData`. +But it also has extra reactive properties: `data.loading` tells you if the fetcher has been called but not returned, and `data.error` tells you if the request has errored out; if so, it contains the error thrown by the fetcher. (Note: if you anticipate errors, you may want to wrap `createResource` in an [ErrorBoundary](#).) + +As of **1.4.0**, `data.latest` will return the last returned value and won't trigger [Suspense](#) and [transitions](#usetransition); if no value has been returned yet, `data.latest` acts the same as `data()`. This can be useful if you want to show the out-of-date data while the new data is loading. + +`loading`, `error`, and `latest` are reactive getters and can be tracked. + +The `fetcher` is the async function that you provide to `createResource` to actually fetch the data. +It is passed two arguments: the value of the source signal (if provided), and an info object with two properties: `value` and `refetching`. `value` tells you the previously fetched value. +`refetching` is `true` if the fetcher was triggered using the `refetch` function and `false` otherwise. +If the `refetch` function was called with an argument (`refetch(info)`), `refetching` is set to that argument. + +```js +async function fetchData(source, { value, refetching }) { + // Fetch the data and return a value. + //`source` tells you the current value of the source signal; + //`value` tells you the last returned value of the fetcher; + //`refetching` is true when the fetcher is triggered by calling `refetch()`, + // or equal to the optional data passed: `refetch(info)` +} + +const [data, { mutate, refetch }] = createResource(getQuery, fetchData); + +// read value +data(); + +// check if loading +data.loading; + +// check if errored +data.error; + +// directly set value without creating promise +mutate(optimisticValue); + +// refetch the last request explicitly +refetch(); +``` + +**New in v1.4.0** + +If you're using `renderToStream`, you can tell Solid to wait for a resource before flushing the stream using the `deferStream` option: + +```js +// fetches a user and streams content as soon as possible +const [user] = createResource(() => params.id, fetchUser); + +// fetches a user but only streams content after this resource has loaded +const [user] = createResource(() => params.id, fetchUser, { + deferStream: true, +}); +``` + +**New in v1.5.0** + +We've added a new `state` field which covers a more detailed view of the Resource state beyond `loading` and `error`. You can now check whether a Resource is `"unresolved"`, `"pending"`, `"ready"`, `"refreshing"`, or `"error"`. + +| state | value resolved | loading | has error | +| ---------- | -------------- | ------- | --------- | +| unresolved | No | No | No | +| pending | No | Yes | No | +| ready | Yes | No | No | +| refreshing | Yes | Yes | No | +| errored | No | No | Yes | + +**New in v1.5.0** + +When server rendering resources especially when fetching when embedding Solid in other system that fetch before render, you might want to initiate the resource with this prefetched value instead of fetching again and having the resource serialize it isn't own state. You can use the new `ssrLoadFrom` option for this. Instead of using the default `"server"` value, you can pass `"initial"` and the resource will use `initialValue` as if it were the result of the first fetch for both SSR and hydration. + +**New in 1.5.0** *Experimental* + +Resources can be set with custom defined storage with the same signature as a Signal by using the `storage` option. For example using a custom reconciling store could be done this way: + +```ts +function createDeepSignal(value: T): Signal { + const [store, setStore] = createStore({ + value + }); + return [ + () => store.value, + (v: T) => { + const unwrapped = unwrap(store.value); + typeof v === "function" && (v = v(unwrapped)); + setStore("value", reconcile(v)); + return store.value; + } + ] as Signal; +} + +const [resource] = createResource(fetcher, { + storage: createDeepSignal +}); +``` + +# Lifecycles + +## `onMount` + +```ts +import { onMount } from "solid-js"; + +function onMount(fn: () => void): void; +``` + +Registers a method that runs after initial render and elements have been mounted. Ideal for using `ref`s and managing other one time side effects. It is equivalent to a `createEffect` which does not have any dependencies. + +## `onCleanup` + +```ts +import { onCleanup } from "solid-js"; + +function onCleanup(fn: () => void): void; +``` + +Registers a cleanup method that executes on disposal or recalculation of the current reactive scope. Can be used in any Component or Effect. + +## `onError` + +```ts +import { onError } from "solid-js"; + +function onError(fn: (err: any) => void): void; +``` + +Registers an error handler method that executes when child scope errors. Only the nearest scope error handlers execute. Rethrow to trigger up the line. + +# Reactive Utilities + +These helpers provide the ability to better schedule updates and control how reactivity is tracked. + +## `untrack` + +```ts +import { untrack } from "solid-js"; + +function untrack(fn: () => T): T; +``` + +Ignores tracking any of the dependencies in the executing code block and returns the value. + +## `batch` + +```ts +import { batch } from "solid-js"; + +function batch(fn: () => T): T; +``` + +Holds executing downstream computations within the block until the end to prevent unnecessary recalculation. [Solid Store](#createstore)'s set method, [Mutable Store](#createmutable)'s array methods, and Effects automatically wrap their code in a batch. + +## `on` + +```ts +import { on } from "solid-js"; + +function on any> | (() => any), U>( + deps: T, + fn: (input: T, prevInput: T, prevValue?: U) => U, + options: { defer?: boolean } = {} +): (prevValue?: U) => U | undefined; +``` + +`on` is designed to be passed into a computation to make its dependencies explicit. If an array of dependencies is passed, `input` and `prevInput` are arrays. + +```js +createEffect(on(a, (v) => console.log(v, b()))); + +// is equivalent to: +createEffect(() => { + const v = a(); + untrack(() => console.log(v, b())); +}); +``` + +You can also not run the computation immediately and instead opt in for it to only run on change by setting the defer option to true. + +```js +// doesn't run immediately +createEffect(on(a, (v) => console.log(v), { defer: true })); + +setA("new"); // now it runs +``` + +Please note that on `stores` and `mutable`, adding or removing a property from the parent object will trigger an effect. See [`createMutable`](#createMutable) + +## `createRoot` + +```ts +import { createRoot } from "solid-js"; + +function createRoot(fn: (dispose: () => void) => T): T; +``` + +Creates a new non-tracked owner scope that doesn't auto-dispose. This is useful for nested reactive scopes that you do not wish to release when the parent re-evaluates. + +All Solid code should be wrapped in one of these top level as they ensure that all memory/computations are freed up. Normally you do not need to worry about this as `createRoot` is embedded into all `render` entry functions. + +## `getOwner` + +```ts +import { getOwner } from "solid-js"; + +function getOwner(): Owner; +``` + +Gets the reactive scope that owns the currently running code, e.g., +for passing into a later call to `runWithOwner` outside of the current scope. + +Internally, computations (effects, memos, etc.) create owners which are +children of their owner, all the way up to the root owner created by +`createRoot` or `render`. In particular, this ownership tree lets Solid +automatically clean up a disposed computation by traversing its subtree +and calling all [`onCleanup`](#oncleanup) callbacks. +For example, when a `createEffect`'s dependencies change, the effect calls +all descendant `onCleanup` callbacks before running the effect function again. +Calling `getOwner` returns the current owner node that is responsible +for disposal of the current execution block. + +Components are not computations, so do not create an owner node, but they are +typically rendered from a `createEffect` which does, so the result is similar: +when a component gets unmounted, all descendant `onCleanup` callbacks get +called. Calling `getOwner` from a component scope returns the owner that is +responsible for rendering and unmounting that component. + +Note that the owning reactive scope isn't necessarily _tracking_. +For example, [`untrack`](#untrack) turns off tracking for the duration +of a function (without creating a new reactive scope), as do +components created via JSX (``). + +## `runWithOwner` + +```ts +import { runWithOwner } from 'solid-js'; + +function runWithOwner(owner: Owner, fn: (() => void) => T): T; +``` + +Executes the given function under the provided owner, +instead of (and without affecting) the owner of the outer scope. +By default, computations created by `createEffect`, `createMemo`, etc. +are owned by the owner of the currently executing code (the return value of +`getOwner`), so in particular will get disposed when their owner does. +Calling `runWithOwner` provides a way to override this default to a manually +specified owner (typically, the return value from a previous call to +`getOwner`), enabling more precise control of when computations get disposed. + +Having a (correct) owner is important for two reasons: + +- Computations without an owner cannot be cleaned up. For example, if you call + `createEffect` without an owner (e.g., in the global scope), the effect will + continue running forever, instead of being disposed when its owner gets + disposed. +- [`useContext`](#usecontext) obtains context by walking up the owner tree + to find the nearest ancestor providing the desired context. + So without an owner you cannot look up any provided context + (and with the wrong owner, you might obtain the wrong context). + +Manually setting the owner is especially helpful when doing reactivity outside +of any owner scope. In particular, asynchronous computation +(via either `async` functions or callbacks like `setTimeout`) +lose the automatically set owner, so remembering the original owner via +`getOwner` and restoring it via `runWithOwner` is necessary in these cases. +For example: + +```js +const owner = getOwner(); +setTimeout(() => { + // This callback gets run without owner. + // Restore owner via runWithOwner: + runWithOwner(owner, () => { + const foo = useContext(FooContext); + createEffect(() => { + console.log(foo); + }); + }); +}, 1000); +``` + +Note that owners are not what determines dependency tracking, +so `runWithOwner` does not help with tracking in asynchronous functions; +use of reactive state in the asynchronous part (e.g. after the first `await`) +will not be tracked as a dependency. + +## `mergeProps` + +```ts +import { mergeProps } from "solid-js"; + +function mergeProps(...sources: any): any; +``` + +A reactive object `merge` method. Useful for setting default props for components in case caller doesn't provide them. Or cloning the props object including reactive properties. + +This method works by using a proxy and resolving properties in reverse order. This allows for dynamic tracking of properties that aren't present when the prop object is first merged. + +```js +// default props +props = mergeProps({ name: "Smith" }, props); + +// clone props +newProps = mergeProps(props); + +// merge props +props = mergeProps(props, otherProps); +``` + +## `splitProps` + +```ts +import { splitProps } from "solid-js"; + +function splitProps( + props: T, + ...keys: Array<(keyof T)[]> +): [...parts: Partial]; +``` + +Splits a reactive object by keys. + +It takes a reactive object and any number of arrays of keys; for each array of keys, it will return a reactive object with just those properties of the original object. The last reactive object in the returned array will have any leftover properties of the original object. + +This can be useful if you want to consume a subset of props and pass the rest to a child. + +```js +function MyComponent(props) { + const [local, others] = splitProps(props, ["children"]); + + return ( + <> +
{local.children}
+ + + ); +} +``` + +Because `splitProps` takes any number of arrays, we can split a props object +as much as we wish (if, for example, we had multiple child components that +each required a subset of the props). + +Let's say a component was passed six props: + +```js +; +function MyComponent(props) { + console.log(props); // {a: 1, b: 2, c: 3, d: 4, e: 5, foo: "bar"} + const [vowels, consonants, leftovers] = splitProps( + props, + ["a", "e"], + ["b", "c", "d"] + ); + console.log(vowels); // {a: 1, e: 5} + console.log(consonants); // {b: 2, c: 3, d: 4} + console.log(leftovers.foo); // bar +} +``` + +## `useTransition` + +```ts +import { useTransition } from "solid-js"; + +function useTransition(): [ + pending: () => boolean, + startTransition: (fn: () => void) => Promise +]; +``` + +Used to batch async updates in a transaction deferring commit until all async processes are complete. This is tied into Suspense and only tracks resources read under Suspense boundaries. + +```js +const [isPending, start] = useTransition(); + +// check if transitioning +isPending(); + +// wrap in transition +start(() => setSignal(newValue), () => /* transition is done */) +``` + +## `startTransition` + +**New in v1.1.0** + +```ts +import { startTransition } from 'solid-js'; + +function startTransition: (fn: () => void) => Promise; +``` + +Similar to `useTransition` except there is no associated pending state. This one can just be used directly to start the Transition. + +## `observable` + +```ts +import { observable } from "solid-js"; + +function observable(input: () => T): Observable; +``` + +This method takes a signal and produces an Observable. +You can consume it from another Observable library of your choice, typically +with the `from` operator. + +```js +// How to integrate rxjs with a solid.js signal +import { observable } from "solid-js"; +import { from } from "rxjs"; + +const [s, set] = createSignal(0); + +const obsv$ = from(observable(s)); + +obsv$.subscribe((v) => console.log(v)); +``` + +You can also use `from` without `rxjs`; see below. + +## `from` + +**New in v1.1.0** + +```ts +import { from } from "solid-js"; + +function from( + producer: + | ((setter: (v: T) => T) => () => void) + | { + subscribe: ( + fn: (v: T) => void + ) => (() => void) | { unsubscribe: () => void }; + } +): () => T; +``` + +A helper to make it easier to interop with external producers like RxJS observables or with Svelte Stores. This basically turns any subscribable (object with a `subscribe` method) into a Signal and manages subscription and disposal. + +```js +const signal = from(obsv$); +``` + +It can also take a custom producer function where the function is passed a setter function returns a unsubscribe function: + +```js +const clock = from((set) => { + const t = setInterval(() => set(1), 1000); + return () => clearInterval(t); +}); +``` + +> Note: Signals created by `from` have equality checks turned off to interface better with external streams and sources. + +## `mapArray` + +```ts +import { mapArray } from "solid-js"; + +function mapArray( + list: () => readonly T[], + mapFn: (v: T, i: () => number) => U +): () => U[]; +``` + +Reactive map helper that caches each item by reference to reduce unnecessary mapping on updates. It only runs the mapping function once per value and then moves or removes it as needed. The index argument is a signal. The map function itself is not tracking. + +Underlying helper for the `` control flow. + +```js +const mapped = mapArray(source, (model) => { + const [name, setName] = createSignal(model.name); + const [description, setDescription] = createSignal(model.description); + + return { + id: model.id, + get name() { + return name(); + }, + get description() { + return description(); + }, + setName, + setDescription, + }; +}); +``` + +## `indexArray` + +```ts +import { indexArray } from "solid-js"; + +function indexArray( + list: () => readonly T[], + mapFn: (v: () => T, i: number) => U +): () => U[]; +``` + +Similar to `mapArray` except it maps by index. The item is a signal and the index is now the constant. + +Underlying helper for the `` control flow. + +```js +const mapped = indexArray(source, (model) => { + return { + get id() { + return model().id + } + get firstInitial() { + return model().firstName[0]; + }, + get fullName() { + return `${model().firstName} ${model().lastName}`; + }, + } +}); +``` + +# Stores + +These APIs are available at `solid-js/store`. They allow the creation of stores: [proxy objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) that allow a tree of signals to be independently tracked and modified. + +## Using Stores + +### `createStore` + +```ts +import { createStore } from "solid-js/store"; +import type { StoreNode, Store, SetStoreFunction } from "solid-js/store"; + +function createStore( + state: T | Store +): [get: Store, set: SetStoreFunction]; +type Store = T; // conceptually readonly, but not typed as such +``` + +The create function takes an initial state, wraps it in a store, and returns a readonly proxy object and a setter function. + +```js +const [state, setState] = createStore(initialValue); + +// read value +state.someValue; + +// set value +setState({ merge: "thisValue" }); + +setState("path", "to", "value", newValue); +``` + +As proxies, store objects only track when a property is accessed. + +When nested objects are accessed, stores will produce nested store objects, and this applies all the way down the tree. However, this only applies to arrays and plain objects. Classes are not wrapped, so objects like `Date`, `HTMLElement`, `RegExp`, `Map`, `Set` won't be granularly reactive as properties on a store. + +#### Arrays in stores + +As of version **1.4.0**, the top level state object can be an array. In prior versions, create an object to wrap the array: + +```jsx +//After Solid 1.4.0 +const [todos, setTodos] = createStore([ + { id: 1, title: "Thing I have to do", done: false }, + { id: 2, title: "Learn a New Framework", done: false }, +]); +... +{todo => }; +``` + +```jsx +//Before 1.4.0 +const [state, setState] = createStore({ + todos: [ + { id: 1, title: "Thing I have to do", done: false }, + { id: 2, title: "Learn a New Framework", done: false }, + ], +}); +{(todo) => }; +``` + +Note that modifying an array inside a store will not trigger computations that subscribe to the array directly. For example: + +```js +createEffect(() => { + console.log(state.todos); +}); + +//This will not trigger the effect: +setState(todos, state.todos.length, { id: 3 }); +//This will trigger the effect, because the array reference changes: +setState("todos", (prev) => [...prev, { id: 3 }]); +``` + +### Getters + +Store objects support the use of getters to store calculated values. + +```js +const [state, setState] = createStore({ + user: { + firstName: "John", + lastName: "Smith", + get fullName() { + return `${this.firstName} ${this.lastName}`; + }, + }, +}); +``` + +These are getters that rerun when accessed, +so you still need to use a memo if you want to cache a value: + +```js +let fullName; +const [state, setState] = createStore({ + user: { + firstName: "John", + lastName: "Smith", + get fullName() { + return fullName(); + }, + }, +}); +fullName = createMemo(() => `${state.user.firstName} ${state.user.lastName}`); +``` + +### Updating Stores + +Changes can take the form of function that passes previous state and returns new state or a value. Objects are always shallowly merged. Set values to `undefined` to delete them from the Store. + +```js +const [state, setState] = createStore({ + firstName: "John", + lastName: "Miller", +}); + +setState({ firstName: "Johnny", middleName: "Lee" }); +// ({ firstName: 'Johnny', middleName: 'Lee', lastName: 'Miller' }) + +setState((state) => ({ preferredName: state.firstName, lastName: "Milner" })); +// ({ firstName: 'Johnny', preferredName: 'Johnny', middleName: 'Lee', lastName: 'Milner' }) +``` + +It supports paths including key arrays, object ranges, and filter functions. + +setState also supports nested setting where you can indicate the path to the change. When nested the state you are updating may be other non Object values. Objects are still merged but other values (including Arrays) are replaced. + +```js +const [state, setState] = createStore({ + counter: 2, + list: [ + { id: 23, title: 'Birds' } + { id: 27, title: 'Fish' } + ] +}); + +setState('counter', c => c + 1); +setState('list', l => [...l, {id: 43, title: 'Marsupials'}]); +setState('list', 2, 'read', true); +// { +// counter: 3, +// list: [ +// { id: 23, title: 'Birds' } +// { id: 27, title: 'Fish' } +// { id: 43, title: 'Marsupials', read: true } +// ] +// } +``` + +Path can be string keys, array of keys, iterating objects ({from, to, by}), or filter functions. This gives incredible expressive power to describe state changes. + +```js +const [state, setState] = createStore({ + todos: [ + { task: 'Finish work', completed: false } + { task: 'Go grocery shopping', completed: false } + { task: 'Make dinner', completed: false } + ] +}); + +setState('todos', [0, 2], 'completed', true); +// { +// todos: [ +// { task: 'Finish work', completed: true } +// { task: 'Go grocery shopping', completed: false } +// { task: 'Make dinner', completed: true } +// ] +// } + +setState('todos', { from: 0, to: 1 }, 'completed', c => !c); +// { +// todos: [ +// { task: 'Finish work', completed: false } +// { task: 'Go grocery shopping', completed: true } +// { task: 'Make dinner', completed: true } +// ] +// } + +setState('todos', todo => todo.completed, 'task', t => t + '!') +// { +// todos: [ +// { task: 'Finish work', completed: false } +// { task: 'Go grocery shopping!', completed: true } +// { task: 'Make dinner!', completed: true } +// ] +// } + +setState('todos', {}, todo => ({ marked: true, completed: !todo.completed })) +// { +// todos: [ +// { task: 'Finish work', completed: true, marked: true } +// { task: 'Go grocery shopping!', completed: false, marked: true } +// { task: 'Make dinner!', completed: false, marked: true } +// ] +// } +``` + +## Store Utilities + +### `produce` + +```ts +import { produce } from "solid-js/store"; + +function produce( + fn: (state: T) => void +): ( + state: T extends NotWrappable ? T : Store +) => T extends NotWrappable ? T : Store; +``` + +Immer inspired API for Solid's Store objects that allows for localized mutation. + +```js +setState( + produce((s) => { + s.user.name = "Frank"; + s.list.push("Pencil Crayon"); + }) +); +``` + +### `reconcile` + +```ts +import { reconcile } from "solid-js/store"; + +function reconcile( + value: T | Store, + options?: { + key?: string | null; + merge?: boolean; + } = { key: "id" } +): ( + state: T extends NotWrappable ? T : Store +) => T extends NotWrappable ? T : Store; +``` + +Diffs data changes when we can't apply granular updates. Useful for when dealing with immutable data from stores or large API responses. + +The key is used when available to match items. By default `merge` false does referential checks where possible to determine equality and replaces where items are not referentially equal. `merge` true pushes all diffing to the leaves and effectively morphs the previous data to the new value. + +```js +// subscribing to an observable +const unsubscribe = store.subscribe(({ todos }) => ( + setState('todos', reconcile(todos))); +); +onCleanup(() => unsubscribe()); +``` + +### `unwrap` + +```ts +import { unwrap } from "solid-js/store"; + +function unwrap(store: Store): T; +``` + +Returns the underlying data in the store without a proxy. + +### `createMutable` + +```ts +import { createMutable } from 'solid-js/store'; + +function createMutable( + state: T | Store, +): Store; +``` + +Creates a new mutable Store proxy object. Stores only trigger updates on values changing. Tracking is done by intercepting property access and automatically tracks deep nesting via proxy. + +Useful for integrating external systems or as a compatibility layer with MobX/Vue. + +> **Note:** A mutable state can be passed around and mutated anywhere, which can make it harder to follow and easier to break unidirectional flow. It is generally recommended to use `createStore` instead. The `produce` modifier can give many of the same benefits without any of the downsides. + +```js +const state = createMutable(initialValue); + +// read value +state.someValue; + +// set value +state.someValue = 5; + +state.list.push(anotherValue); +``` + +Mutables support setters along with getters. + +```js +const user = createMutable({ + firstName: "John", + lastName: "Smith", + get fullName() { + return `${this.firstName} ${this.lastName}`; + }, + set fullName(value) { + [this.firstName, this.lastName] = value.split(" "); + }, +}); +``` + +### `modifyMutable` + +**New in v1.4.0** + +```ts +import { modifyMutable } from 'solid-js/store'; + +function modifyMutable(mutable: T, modifier: (state: T) => T): void; +``` + +This helper function simplifies making multiple changes to a mutable Store +(as returned by [`createMutable`](#createmutable)) +in a single [`batch`](#batch), +so that dependant computations update just once instead of once per update. +The first argument is the mutable Store to modify, +and the second argument is a Store modifier such as those returned by +[`reconcile`](#reconcile) or [`produce`](#produce). +(If you pass in your own modifier function, beware that its argument is +an unwrapped version of the Store.) + +For example, suppose we have a UI depending on multiple fields of a mutable: + +```tsx +const state = createMutable({ + user: { + firstName: "John", + lastName: "Smith", + }, +}); + +

Hello {state.user.firstName + ' ' + state.user.lastName}

+``` + +Modifying *n* fields in sequence will cause the UI to update *n* times: + +```ts +state.user.firstName = "Jake"; // triggers update +state.user.lastName = "Johnson"; // triggers another update +``` + +To trigger just a single update, we could modify the fields in a `batch`: + +```ts +batch(() => { + state.user.firstName = "Jake"; + state.user.lastName = "Johnson"; +}); +``` + +`modifyMutable` combined with `reconcile` or `produce` +provides two alternate ways to do similar things: + +```ts +// Replace state.user with the specified object (deleting any other fields) +modifyMutable(state.user, reconcile({ + firstName: "Jake", + lastName: "Johnson", +}); + +// Modify two fields in batch, triggering just one update +modifyMutable(state.user, produce((u) => { + u.firstName = "Jake"; + u.lastName = "Johnson"; +}); +``` + +# Component APIs + +## `createContext` + +```ts +import { createContext } from "solid-js"; +import type { Context } from "solid-js"; + +interface Context { + id: symbol; + Provider: (props: { value: T; children: any }) => any; + defaultValue: T; +} + +function createContext(defaultValue?: T): Context; +``` + +Context provides a form of dependency injection in Solid. It is used to save from needing to pass data as props through intermediate components. + +This function creates a new context object that can be used with `useContext` and provides the `Provider` control flow. Default Context is used when no `Provider` is found above in the hierarchy. + +```js +export const CounterContext = createContext([{ count: 0 }, {}]); + +export function CounterProvider(props) { + const [state, setState] = createStore({ count: props.count || 0 }); + const counter = [ + state, + { + increment() { + setState("count", (c) => c + 1); + }, + decrement() { + setState("count", (c) => c - 1); + }, + }, + ]; + + return ( + + {props.children} + + ); +} +``` + +The value passed to provider is passed to `useContext` as is. That means wrapping as a reactive expression will not work. You should pass in Signals and Stores directly instead of accessing them in the JSX. + +## `useContext` + +```ts +import { useContext } from "solid-js"; + +function useContext(context: Context): T; +``` + +Used to grab context to allow for deep passing of props without having to pass them through each Component function. + +```js +const [state, { increment, decrement }] = useContext(CounterContext); +``` + +## `children` + +```ts +import { children } from "solid-js"; +import type { JSX, ResolvedChildren } from "solid-js"; + +function children(fn: () => JSX.Element): () => ResolvedChildren; +``` + +The `children` helper is for complicated interactions with `props.children`, +when you're not just passing children on to another component +using `{props.children}` once in JSX. +Normally you pass in a getter for `props.children` like so: + +```js +const resolved = children(() => props.children); +``` + +The return value is a [memo](#creatememo) evaluating to the resolved children, +which updates whenever the children change. +Using this memo instead of accessing `props.children` directly +has some important advantages in some scenarios. +The underlying issue is that, when you specify component children via JSX, +Solid automatically defines `props.children` as a property getter, +so that the children are created (in particular, DOM is created) +whenever `props.children` gets accessed. Two particular consequences: + +- If you access `props.children` multiple times, the children + (and associated DOM) get created multiple times. + This is useful if you want the DOM to be duplicated (as DOM nodes can appear + in only one parent element), but in many cases it creates redundant DOM nodes. + If you instead call `resolved()` multiple times, you re-use the same children. +- If you access `props.children` outside of a tracking scope (e.g., in an + event handler), then you create children that will never be cleaned up. + If you instead call `resolved()`, you re-use the already resolved children. + You also guarantee that the children are tracked in the current component, + as opposed to another tracking scope such as another component. + +In addition, the `children` helper "resolves" children by +calling argumentless functions and flattening arrays of arrays into an array. +For example, a child specified with JSX like `{signal() * 2}` gets wrapped into +a getter function `() => count() * 2` in `props.children`, but gets evaluated +to an actual number in `resolved`, properly depending on a `count` signal. + +If the given `props.children` is not an array +(which occurs when the JSX tag has a single child), +then the `children` helper will not normalize it into an array. +This is useful behavior e.g. when the intention is to pass a single function +as a child, which can be detected via `typeof resolved() === 'function'`. +If you want to normalize to an array, the returned memo has a `toArray` method(*new in 1.5*). + +Here is an example of automatically setting the `class` attribute of any +child that resolves to an `Element`, in addition to rendering the children: + +```tsx +const resolved = children(() => props.children); + +createEffect(() => { + let list = resolved.toArray(); + for (let child of list) child?.setAttribute?.("class", myClass()); +}); + +return
{resolved()}
; +``` + +(Note that this approach is not particularly recommended: +it is usually better to follow a declarative approach of passing +in the desired class via props or context to the children components.) + +On the other hand, you don't need (and in some cases, don't want) +to use the `children` helper if you're just passing `props.children` +on to another component or element via JSX: + +```tsx +const Wrapper = (props) => { + return
{props.children}
; +}; +``` + +An important aspect of the `children` helper is that it forces the children +to be created and resolved, as it accesses `props.children` immediately. +This can be undesirable for conditional rendering, +e.g., when using the children within a [``](#) component. +For example, the following code always evaluates the children: + +```tsx +const resolved = children(() => props.children); + +return {resolved()}; +``` + +To evaluate the children only when `` would render them, you can +push the call to `children` inside a component or a function within ``, +which only evaluates its children when the `when` condition is true. +Another nice workaround is to pass `props.children` to the `children` helper +only when you actually want to evaluate the children: + +```ts +const resolved = children(() => visible() && props.children); +``` + +## `lazy` + +```ts +import { lazy } from "solid-js"; + +function lazy>( + fn: () => Promise<{ default: T }> +): T & { preload: () => Promise }; +``` + +Used to lazy load components to allow for code splitting. Components are not loaded until rendered. Lazy loaded components can be used the same as its statically imported counterpart, receiving props etc... Lazy components trigger `` + +```js +// wrap import +const ComponentA = lazy(() => import("./ComponentA")); + +// use in JSX +; +``` + +## `createUniqueId` + +```ts +import { createUniqueId } from "solid-js"; + +function createUniqueId(): string; +``` + +A universal id generator that is stable across server/browser. + +```js +const id = createUniqueId(); +``` + +> **Note** on the server this only works under hydratable components + +# Secondary Primitives + +You probably won't need them for your first app, but these are useful tools to have. + +## `createDeferred` + +```ts +import { createDeferred } from "solid-js"; + +function createDeferred( + source: () => T, + options?: { + timeoutMs?: number; + equals?: false | ((prev: T, next: T) => boolean); + } +): () => T; +``` + +Creates a readonly that only notifies downstream changes when the browser is idle. `timeoutMs` is the maximum time to wait before forcing the update. + +## `createRenderEffect` + +```ts +import { createRenderEffect } from "solid-js"; + +function createRenderEffect(fn: (v: T) => T, value?: T): void; +``` + +A render effect is a computation similar to a regular effect +(as created by [`createEffect`](#createeffect)), +but differs in when Solid schedules the first execution of the effect function. +While `createEffect` waits for the current rendering phase to be complete, +`createRenderEffect` immediately calls the function. +Thus the effect runs as DOM elements are being created and updated, +but possibly before specific elements of interest have been created, +and probably before those elements have been connected to the document. +In particular, [`ref`](#ref)s will not be set before the initial effect call. +Indeed, Solid uses `createRenderEffect` to implement the rendering phase +itself, including setting of `ref`s. + +Reactive updates to render effects are identical to effects: they queue up in +response to a reactive change (e.g., a single signal update, or a `batch` of +changes, or collective changes during an entire render phase) and run in a +single [`batch`](#batch) afterward (together with effects). +In particular, all signal updates within a render effect are batched. + +Here is an example of the behavior. +(Compare with the example in [`createEffect`](#createeffect).) + +```js +// assume this code is in a component function, so is part of a rendering phase +const [count, setCount] = createSignal(0); + +// this effect prints count at the beginning and when it changes +createRenderEffect(() => console.log("count =", count())); +// render effect runs immediately, printing `count = 0` +console.log("hello"); +setCount(1); // effect won't run yet +setCount(2); // effect won't run yet + +queueMicrotask(() => { + // now `count = 2` will print + console.log("microtask"); + setCount(3); // immediately prints `count = 3` + console.log("goodbye"); +}); + +// --- overall output: --- +// count = 0 [this is the only added line compared to createEffect] +// hello +// count = 2 +// microtask +// count = 3 +// goodbye +``` + +Just like `createEffect`, the effect function gets called with an argument +equal to the value returned from the effect function's last execution, +or on the first call, equal to the optional second argument to +`createRenderEffect`. + +## `createComputed` + +```ts +import { createComputed } from "solid-js"; + +function createComputed(fn: (v: T) => T, value?: T): void; +``` + +`createComputed` creates a new computation that immediately runs the given +function in a tracking scope, thus automatically tracking its dependencies, +and automatically reruns the function whenever the dependencies changes. +The function gets called with an argument equal to the value returned +from the function's last execution, or on the first call, +equal to the optional second argument to `createComputed`. +Note that the return value of the function is not otherwise exposed; +in particular, `createComputed` has no return value. + +`createComputed` is the most immediate form of reactivity in Solid, and is +most useful for building other reactive primitives. +(For example, some other Solid primitives are built from `createComputed`.) +But it should be used with care, as `createComputed` can easily cause more +unnecessary updates than other reactive primitives. +Before using it, consider the closely related primitives +[`createMemo`](#creatememo) and [`createRenderEffect`](#createrendereffect). + +Like `createMemo`, `createComputed` calls its function immediately on updates +(unless you're in a [batch](#batch), [effect](#createEffect), or +[transition](#use-transition)). +However, while `createMemo` functions should be pure (not set any signals), +`createComputed` functions can set signals. +Related, `createMemo` offers a readonly signal for the return value of the +function, whereas to do the same with `createComputed` you would need to +set a signal within the function. +If it is possible to use pure functions and `createMemo`, this is likely +more efficient, as Solid optimizes the execution order of memo updates, +whereas updating a signal within `createComputed` will immediately trigger +reactive updates some of which may turn out to be unnecessary. + +Like `createRenderEffect`, `createComputed` calls its function for the first +time immediately. But they differ in how updates are performed. +While `createComputed` generally updates immediately, `createRenderEffect` +updates queue to run (along with `createEffect`s) +after the current render phase. +Thus `createRenderEffect` can perform fewer overall updates, +but is slightly less immediate. + +## `createReaction` + +**New in v1.3.0** + +```ts +import { createReaction } from "solid-js"; + +function createReaction(onInvalidate: () => void): (fn: () => void) => void; +``` + +Sometimes it is useful to separate tracking from re-execution. This primitive registers a side effect that is run the first time the expression wrapped by the returned tracking function is notified of a change. + +```js +const [s, set] = createSignal("start"); + +const track = createReaction(() => console.log("something")); + +// next time s changes run the reaction +track(() => s()); + +set("end"); // "something" + +set("final"); // no-op as reaction only runs on first update, need to call track again. +``` + +## `createSelector` + +```ts +import { createSelector } from "solid-js"; + +function createSelector( + source: () => T, + fn?: (a: U, b: T) => boolean +): (k: U) => boolean; +``` + +Creates a conditional signal that only notifies subscribers when entering or exiting their key matching the value. Useful for delegated selection state. As it makes the operation O(1) instead of O(n). + +```js +const isSelected = createSelector(selectedId); + + + {(item) =>
  • {item.name}
  • } +
    ; +``` + +# Rendering + +These imports are exposed from `solid-js/web`. + +## `render` + +```ts +import { render } from "solid-js/web"; +import type { JSX, MountableElement } from "solid-js/web"; + +function render(code: () => JSX.Element, element: MountableElement): () => void; +``` + +This is the browser app entry point. +Provide a top-level component function and an element to mount to. +It is recommended this element be empty: +while `render` will just append children, +the returned `dispose` function will remove all children. + +```js +const dispose = render(App, document.getElementById("app")); +// or +const dispose = render(() => , document.getElementById("app")); +``` + +It's important that the first argument is a function: do not pass JSX directly +(as in `render(, ...)`), because this will call `App` before `render` can +set up a root to track signal dependencies within `App`. + +## `hydrate` + +```ts +import { hydrate } from "solid-js/web"; + +function hydrate(fn: () => JSX.Element, node: MountableElement): () => void; +``` + +This method is similar to `render` except it attempts to rehydrate what is already rendered to the DOM. When initializing in the browser a page has already been server rendered. + +```js +const dispose = hydrate(App, document.getElementById("app")); +``` + +## `renderToString` + +```ts +import { renderToString } from "solid-js/web"; + +function renderToString( + fn: () => T, + options?: { + nonce?: string; + renderId?: string; + } +): string; +``` + +Renders to a string synchronously. The function also generates a script tag for progressive hydration. Options include eventNames to listen to before the page loads and play back on hydration, and nonce to put on the script tag. + +`renderId` is used to namespace renders when having multiple top level roots. + +```js +const html = renderToString(App); +``` + +## `renderToStringAsync` + +```ts +import { renderToStringAsync } from "solid-js/web"; + +function renderToStringAsync( + fn: () => T, + options?: { + timeoutMs?: number; + renderId?: string; + nonce?: string; + } +): Promise; +``` + +Same as `renderToString` except it will wait for all `` boundaries to resolve before returning the results. Resource data is automatically serialized into the script tag and will be hydrated on client load. + +`renderId` is used to namespace renders when having multiple top level roots. + +```js +const html = await renderToStringAsync(App); +``` + +## `renderToStream` + +**New in v1.3.0** + +```ts +import { renderToStream } from "solid-js/web"; + +function renderToStream( + fn: () => T, + options?: { + nonce?: string; + renderId?: string; + onCompleteShell?: () => void; + onCompleteAll?: () => void; + } +): { + pipe: (writable: { write: (v: string) => void }) => void; + pipeTo: (writable: WritableStream) => void; +}; +``` + +This method renders to a stream. It renders the content synchronously including any Suspense fallback placeholders, and then continues to stream the data and HTML from any async resource as it completes. + +```js +// node +renderToStream(App).pipe(res); + +// web stream +const { readable, writable } = new TransformStream(); +renderToStream(App).pipeTo(writable); +``` + +`onCompleteShell` fires when synchronous rendering is complete before writing the first flush to the stream out to the browser. `onCompleteAll` is called when all server Suspense boundaries have settled. `renderId` is used to namespace renders when having multiple top level roots. + +> Note this API replaces the previous `pipeToWritable` and `pipeToNodeWritable` APIs. + +## `isServer` + +```ts +import { isServer } from "solid-js/web"; + +const isServer: boolean; +``` + +This indicates that the code is being run as the server or browser bundle. As the underlying runtimes export this as a constant boolean it allows bundlers to eliminate the code and their used imports from the respective bundles. + +```js +if (isServer) { + // I will never make it to the browser bundle +} else { + // won't be run on the server; +} +``` + +## `DEV` + +```ts +import { DEV } from "solid-js"; + +const DEV: object | undefined; +``` + +On the client, Solid provides +(via [conditional exports](https://nodejs.org/api/packages.html#conditional-exports)) +different builds depending on whether the `development` condition is set. +Development mode provides some additional checking — e.g. detecting accidental +use of multiple instances of Solid — which are removed in production builds. + +If you want code to run only in development mode (most useful in libraries), +you can check whether the `DEV` export is defined. Note that it is always +defined on the server, so you may want to combine with [`isServer`](#isserver): + +```ts +import { DEV } from "solid-js"; +import { isServer } from "solid-js/web"; + +if (DEV && !isServer) { + console.log(...); +} +``` + +## `HydrationScript` + +```ts +import { generateHydrationScript, HydrationScript } from "solid-js/web"; + +function generateHydrationScript(options: { + nonce?: string; + eventNames?: string[]; +}): string; + +function HydrationScript(props: { + nonce?: string; + eventNames?: string[]; +}): JSX.Element; +``` + +Hydration Script is a special script that should be placed once on the page to bootstrap hydration before Solid's runtime has loaded. It comes both as a function that can be called and inserted in an your HTML string, or as a Component if you are rendering JSX from the `` tag. + +The options are for the `nonce` to be put on the script tag and any event names for that Solid should capture before scripts have loaded and replay during hydration. These events are limited to those that Solid delegates which include most UI Events that are composed and bubble. By default it is only `click` and `input` events. + +# Control Flow + +For reactive control flow to be performant, we have to control how elements are created. For example, calling `array.map` is inefficient as it always maps the entire array. + +This means helper functions. Wrapping these in components is convenient way for terse templating and allows users to compose and build their own control flow components. + +These built-in control flow components will be automatically imported. All except `Portal` and `Dynamic` are exported from both `solid-js` and `solid-js/web`. `Portal` and `Dynamic`, which are DOM-specific, are exported by `solid-js/web`. + +> Note: All callback/render function children of control flow are non-tracking. This allows for nesting state creation, and better isolates reactions. + +## `` + +```ts +import { For } from "solid-js"; + +function For(props: { + each: readonly T[]; + fallback?: JSX.Element; + children: (item: T, index: () => number) => U; +}): () => U[]; +``` + +A referentially keyed loop with efficient updating of only changed items. +The callback takes the current item as the first argument: + +```jsx +Loading...}> + {(item) =>
    {item}
    } +
    +``` + +The optional second argument is an index signal: + +```jsx +Loading...}> + {(item, index) => ( +
    + #{index()} {item} +
    + )} +
    +``` + +## `` + +```ts +import { Show } from "solid-js"; + +function Show(props: { + when: T | undefined | null | false; + keyed: boolean; + fallback?: JSX.Element; + children: JSX.Element | ((item: T) => JSX.Element); +}): () => JSX.Element; +``` + +The Show control flow is used to conditional render part of the view: it renders `children` when the `when` is truthy, an `fallback` otherwise. It is similar to the ternary operator (`when ? children : fallback`) but is ideal for templating JSX. + +```jsx + 0} fallback={
    Loading...
    }> +
    My Content
    +
    +``` + +Show can also be used as a way of keying blocks to a specific data model. Ex the function is re-executed whenever the user model is replaced. + +```jsx +Loading...} keyed> + {(user) =>
    {user.firstName}
    } +
    +``` + +## ``/`` + +```ts +import { Switch, Match } from "solid-js"; +import type { MatchProps } from "solid-js"; + +function Switch(props: { + fallback?: JSX.Element; + children: JSX.Element; +}): () => JSX.Element; + +type MatchProps = { + when: T | undefined | null | false; + children: JSX.Element | ((item: T) => JSX.Element); +}; +function Match(props: MatchProps); +``` + +Useful for when there are more than 2 mutual exclusive conditions. +For example, it can be used to perform basic routing: + +```jsx +Not Found}> + + + + + + + +``` + +Match also supports function children to serve as keyed flow. + +## `` + +```ts +import { Index } from "solid-js"; + +function Index(props: { + each: readonly T[]; + fallback?: JSX.Element; + children: (item: () => T, index: number) => U; +}): () => U[]; +``` + +Non-keyed list iteration (rendered nodes are keyed to an array index). This is useful when there is no conceptual key, like if the data consists of primitives and it is the index that is fixed rather than the value. + +The item is a signal: + +```jsx +Loading...}> + {(item) =>
    {item()}
    } +
    +``` + +Optional second argument is an index number: + +```jsx +Loading...}> + {(item, index) => ( +
    + #{index} {item()} +
    + )} +
    +``` + +## `` + +```ts +import { ErrorBoundary } from "solid-js"; + +function ErrorBoundary(props: { + fallback: JSX.Element | ((err: any, reset: () => void) => JSX.Element); + children: JSX.Element; +}): () => JSX.Element; +``` + +Catches uncaught errors and renders fallback content. + +```jsx +Something went terribly wrong}> + + +``` + +Also supports callback form which passes in error and a reset function. + +```jsx +
    Error: {err.toString()}
    } +> + +
    +``` + +## `` + +```ts +import { Suspense } from "solid-js"; + +function Suspense(props: { + fallback?: JSX.Element; + children: JSX.Element; +}): JSX.Element; +``` + +A component that tracks all resources read under it and shows a fallback placeholder state until they are resolved. What makes `Suspense` different than `Show` is it is non-blocking in that both branches exist at the same time even if not currently in the DOM. + +```jsx +Loading...}> + + +``` + +## `` (Experimental) + +```ts +import { SuspenseList } from "solid-js"; + +function SuspenseList(props: { + children: JSX.Element; + revealOrder: "forwards" | "backwards" | "together"; + tail?: "collapsed" | "hidden"; +}): JSX.Element; +``` + +`SuspenseList` allows for coordinating multiple parallel `Suspense` and `SuspenseList` components. It controls the order in which content is revealed to reduce layout thrashing and has an option to collapse or hide fallback states. + +```jsx + + + Loading posts...}> + + + Loading fun facts...}> + + + +``` + +SuspenseList is still experimental and does not have full SSR support. + +## `` + +```ts +import { Dynamic } from "solid-js/web"; + +function Dynamic( + props: T & { + children?: any; + component?: Component | string | keyof JSX.IntrinsicElements; + } +): () => JSX.Element; +``` + +This component lets you insert an arbitrary Component or tag and passes the props through to it. + +```jsx + +``` + +## `` + +```ts +import { Portal } from "solid-js/web"; + +function Portal(props: { + mount?: Node; + useShadow?: boolean; + isSVG?: boolean; + children: JSX.Element; +}): Text; +``` + +This inserts the element in the mount node. Useful for inserting Modals outside of the page layout. Events still propagate through the Component Hierarchy. + +The portal is mounted in a `
    ` unless the target is the document head. `useShadow` places the element in a Shadow Root for style isolation, and `isSVG` is required if inserting into an SVG element so that the `
    ` is not inserted. + +```jsx + +
    My Content
    +
    +``` + +# Special JSX Attributes + +In general Solid attempts to stick to DOM conventions. Most props are treated as attributes on native elements and properties on Web Components, but a few of them have special behavior. + +For custom namespaced attributes with TypeScript you need to extend Solid's JSX namespace: + +```ts +declare module "solid-js" { + namespace JSX { + interface Directives { + // use:____ + } + interface ExplicitProperties { + // prop:____ + } + interface ExplicitAttributes { + // attr:____ + } + interface CustomEvents { + // on:____ + } + interface CustomCaptureEvents { + // oncapture:____ + } + } +} +``` + +## `ref` + +Refs are a way of getting access to underlying DOM elements in our JSX. While it is true one could just assign an element to a variable, it is more optimal to leave components in the flow of JSX. Refs are assigned at render time but before the elements are connected to the DOM. They come in 2 flavors. + +```js +// variable assigned directly by ref +let myDiv; + +// use onMount or createEffect to read after connected to DOM +onMount(() => console.log(myDiv)); + +
    + +// Or, callback function (called before connected to DOM) +
    console.log(el)} /> +``` + +Refs can also be used on Components. They still need to be attached on the other side. + +```jsx +function MyComp(props) { + return
    ; +} + +function App() { + let myDiv; + onMount(() => console.log(myDiv.clientWidth)); + return ; +} +``` + +## `classList` + +Solid offers two ways to set the `class` of an element: +`class` and `classList` attributes. + +First, you can set `class=...` like any other attribute. For example: + +```jsx +// Two static classes +
    + +// One dynamic class, deleting class attribute if it's not needed +
    + +// Two dynamic classes +
    +``` + +(Note that `className=...` was deprecated in Solid 1.4.) + +Alternatively, the `classList` pseudo-attribute lets you specify an object, +where each key is a class and the value is treated as a boolean +representing whether to include that class. +For example (matching the last example): + +```jsx +
    +``` + +This example compiles to a [render effect](#createrendereffect) +that dynamically calls +[`element.classList.toggle`](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle) +to turn each class on or off, only when the corresponding boolean changes. +For example, when `state.active` becomes `true` [`false`], the element gains +[loses] the `active` class. + +The value passed into `classList` can be any expression (including a signal +getter) that evaluates to an appropriate object. Some examples: + +```jsx +// Dynamic class name and value +
    ; + +// Signal class list +const [classes, setClasses] = createSignal({}); +setClasses((c) => ({ ...c, active: true })); +
    ; +``` + +It's also possible, but dangerous, to mix `class` and `classList`. +The main safe situation is when `class` is set to a static string (or nothing), +and `classList` is reactive. +(`class` could also be set to a static computed value as in +`class={baseClass()}`, but then it should appear +before any `classList` pseudo-attributes.) +If both `class` and `classList` are reactive, +you can get unexpected behavior: +when the `class` value changes, Solid sets the entire `class` attribute, +so will overwrite any toggles made by `classList`. + +Because `classList` is a compile-time pseudo-attribute, +it does not work in a prop spread like `
    ` +or in ``. + +## `style` + +Solid's `style` attribute lets you provide either a CSS string or +an object where keys are CSS property names: + +```jsx +// string +
    + +// object +
    +``` + +Unlike [React's `style` attribute](https://reactjs.org/docs/dom-elements.html#style), +Solid uses `element.style.setProperty` under the hood. This means you need to use +the lower-case, dash-separated version of property names +instead of the JavaScript camel-cased version, +such as `"background-color"` rather than `backgroundColor`. +This actually leads to better performance and consistency with SSR output. + +```jsx +// string +
    + +// object +
    +``` + +This also means you can set CSS variables! For example: + +```jsx +// set css variable +
    +``` + +## `innerHTML`/`textContent` + +These work the same as their property equivalent. Set a string and they will be set. **Be careful!!** Setting `innerHTML` with any data that could be exposed to an end user as it could be a vector for malicious attack. `textContent` while generally not needed is actually a performance optimization when you know the children will only be text as it bypasses the generic diffing routine. + +```jsx +
    +``` + +## `on___` + +Event handlers in Solid typically take the form of `onclick` or `onClick` depending on style. + +Solid uses semi-synthetic event delegation for common UI events that are composed and bubble. This improves performance for these common events. + +```jsx +
    console.log(e.currentTarget)} /> +``` + +Solid also supports passing an array to the event handler to bind a value to the first argument of the event handler. This doesn't use `bind` or create an additional closure, so it is a highly optimized way of delegating events. + +```jsx +function handler(itemId, e) { + /*...*/ +} + +
      + {(item) =>
    • } +
    ; +``` + +Events are never rebound and the bindings are not reactive, as it is expensive to attach and detach listeners. +Since event handlers are called like any other function each time an event fires, there is no need for reactivity; shortcut your handler if desired. + +```jsx +// if defined, call it; otherwise don't. +
    props.handleClick?.()} /> +``` + +Note that `onChange` and `onInput` work according to their native behavior. `onInput` will fire immediately after the value has changed; for `` fields, `onChange` will only fire after the field loses focus. + +## `on:___`/`oncapture:___` + +For any other events, perhaps ones with unusual names, or ones you wish not to be delegated, there are the `on` namespace events. This attribute adds an event listener verbatim. + +```jsx +
    alert(e.detail)} /> +``` + +## `use:___` + +These are custom directives. In a sense this is just syntax sugar over ref but allows us to easily attach multiple directives to a single element. A directive is a function with the following signature: + +```ts +function directive(element: Element, accessor: () => any): void; +``` + +Directive functions are called at render time but before being added to the DOM. You can do whatever you'd like in them including create signals, effects, register clean-up etc. + +```js +const [name, setName] = createSignal(""); + +function model(el, value) { + const [field, setField] = value(); + createRenderEffect(() => (el.value = field())); + el.addEventListener("input", (e) => setField(e.target.value)); +} + +; +``` + +To register with TypeScript extend the JSX namespace. + +```ts +declare module "solid-js" { + namespace JSX { + interface Directives { + model: [() => any, (v: any) => any]; + } + } +} +``` + +## `prop:___` + +Forces the prop to be treated as a property instead of an attribute. + +```jsx +
    +``` + +## `attr:___` + +Forces the prop to be treated as a attribute instead of an property. Useful for Web Components where you want to set attributes. + +```jsx + +``` + +## `/* @once */` + +Solid's compiler uses a heuristic for reactive wrapping and lazy evaluation of JSX expressions. Does it contain a function call, a property access, or JSX? If yes we wrap it in a getter when passed to components or in an effect if passed to native elements. + +Knowing this heuristic and its limitations, we can reduce overhead of things we know will never change by accessing them outside of the JSX. A lone variable will never be wrapped. We can also tell the compiler not to wrap them by starting the expression with a comment decorator `/* @once */`. + +```jsx + +``` + +This also works on children. + +```jsx +{/*@once*/ state.wontUpdate} +``` diff --git a/langs/tr/guides/comparison.md b/langs/tr/guides/comparison.md new file mode 100644 index 00000000..ca05c953 --- /dev/null +++ b/langs/tr/guides/comparison.md @@ -0,0 +1,77 @@ +# Comparison with other Libraries + +This section cannot escape some bias but I think it is important to understand where Solid's solution sits compared to other libraries. This is not about performance. For a definitive look at performance feel free to look at the [JS Framework Benchmark](https://github.com/krausest/js-framework-benchmark). + +## React + +React has had a big influence on Solid. Its unidirectional flow and explicit segregation of read and write in its Hooks API informed Solid's API. More so than the objective of being just a "Render Library" rather than a framework. Solid has strong opinions on how to approach managing data in application development but doesn't seek to constrain its execution. + +However, as much as Solid aligns with React's design philosophy, it works fundamentally differently. React uses a Virtual DOM and Solid does not. React's abstraction is top down component partition where render methods are called repeatedly and diffed. Solid, instead, renders each Template once in its entirety, constructing its reactive graph and only then executes instructions related to fine-grained changes. + +#### Advice for migrating: + +Solid's update model is nothing like React, or even React + MobX. Instead of thinking of function components as the `render` function, think of them as a `constructor`. + +In Solid, props and stores are [proxy objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) that rely on property access for tracking and reactive updates. Watch out for destructuring or early property access, which can cause these properties to lose reactivity or trigger at the wrong time. + +Solid's primitives have no restrictions like the Hook Rules so you are free to nest them as you see fit. + +You don't need explicit keys on list rows to have "keyed" behavior. + +In React, `onChange` fires whenever an input field is modified, but this isn't how `onChange` [works natively](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onchange). In Solid, use `onInput` to subscribe to each value change. + +Finally, there is no VDOM so imperative VDOM APIs like `React.Children` and `React.cloneElement` have no equivalent in Solid. Instead of creating or modifying DOM elements directly, express your intentions declaratively. + +## Vue + +Solid is not particularly influenced by Vue design-wise, but they are comparable in approach. They both use Proxies in their Reactive system with read based auto-tracking. But that is where the similarities end. Vue's fine-grained dependency detection just feeds into a less fine-grained Virtual DOM and Component system whereas Solid keeps its granularity right down to its direct DOM updates. + +Vue values easiness where Solid values transparency. Although Vue's new direction with Vue 3 aligns more with the approach Solid takes. These libraries might align more over time depending on how they continue to evolve. + +#### Advice for migrating: + +As another modern reactive library migration from Vue 3 should feel familiar. Solid's components are very much like tagging the template on the end of Vue's `setup` function. Be wary of overwrapping state derivations with computations, try a function. Reactivity is pervasive. Solid's proxies are intentionally read-only. Don't knock it before you try it. + +## Svelte + +Svelte pioneered the precompiled disappearing framework that Solid also employs to a certain degree. Both libraries are truly reactive and can produce really small execution code bundles although Svelte is the winner here for small demos. Solid requires a bit more explicitness in its declarations, relying less on implicit analysis from the compiler, but that is part of what gives Solid superior performance. Solid also keeps more in the runtime which scales better in larger apps. Solid's RealWorld demo implementation is 25% smaller than Svelte's. + +Both libraries aim to help their developers write less code but approach it completely differently. Svelte 3 focuses on the optimization of the ease of dealing with localized change focusing on plain object interaction and two-way binding. In contrast Solid focuses on the data flow by deliberately embracing CQRS and immutable interface. With functional template composition, in many cases, Solid allows developers to write even less code than Svelte although Svelte's template syntax is definitely terser. + +#### Advice for migrating: + +Developer experience is different enough that while some things are analogous it is a very different experience. Components in Solid are cheap, so don't shy away from having more of them. + +## Knockout.js + +This library owes its existence to Knockout. Modernizing its model for fine-grained dependency detection was the motivation for this project. Knockout was released in 2010 and supports Microsoft Explorer back to IE6 while much of Solid doesn't support IE at all. + +Knockout's bindings are just strings in HTML which are walked over at runtime. They depend on cloning context ($parent etc...). Whereas Solid uses JSX or Tagged Template Literals for templating opting for an in JavaScript API. + +The biggest difference might be that Solid's approach to batching changes which ensures synchronicity whereas Knockout has deferUpdates which uses a deferred microtask queue. + +#### Advice for migrating: + +If you are used to Knockout, Solid's primitives might look strange to you. The read/write separation is intentional and not just to make life harder. Look to adopting a state/action (Flux) mental model. While the libraries look similar they promote different best practices. + +## Lit & LighterHTML + +These libraries are incredibly similar and have had some influence on Solid. Mostly that Solid's compiled code uses a very similar method to performantly initially render the DOM. Cloning Template elements and using comment placeholders are something that Solid and these libraries share in common. + +The biggest difference is that while these libraries do not use the Virtual DOM they treat rendering the same way, top down, requiring component partitioning to keep things sane. By contrast, Solid uses its fine-grained Reactive Graph to only update what has changed and in doing so only shares this technique for its initial render. This approach takes advantage from the initial speed only available to native DOM and also have the most performant approach to updates. + +#### Advice for migrating: + +These libraries are pretty minimal and easy to build on top. However, keep in mind that `` isn't just HTMLElement (array or function). Try to keep your things in the JSX template. Hoisting works for the most part but it is best to mentally think of this still as a render library and not a HTMLElement factory. + +## S.js + +This library had the greatest influence on Solid's reactive design. Solid used S.js internally for a couple of years until the feature set placed them on different paths. S.js is one of the most efficient reactive libraries to date. It models everything off synchronous time steps like a digital circuit and ensures consistency without having to do many of the more complicated mechanisms found in libraries like MobX. Solid's reactivity in the end is a sort of hybrid between S and MobX. This gives it greater performance than most reactive libraries (Knockout, MobX, Vue) while retaining the ease of mental model for the developer. S.js ultimately is still the more performant reactive library although the difference is hardly noticeable in all but the most grueling synthetic benchmarks. + +## RxJS + +RxJS is a Reactive library. While Solid has a similar idea of Observable data it uses a much different application of the observer pattern. While Signals are like a restricted form of an Observable (only the next), the pattern of auto dependency detection supplants RxJS' hundred or so operators. Solid could have taken this approach, and indeed earlier, versions of the library included similar operators, but in most cases it is more straightforward to write your own transformation logic in a computation. Where Observables are cold starting, unicast and push-based, many problems on the client lend themselves to hot startup and being multicast which is Solid's default behavior. + +## Others + +Angular and a few other popular libraries are notably missing from this comparison. Lack of experience with them prevents making any adequate comparisons. Generally, Solid has little in common with larger Frameworks and it is much harder to compare them head on. diff --git a/langs/tr/guides/directory.json b/langs/tr/guides/directory.json new file mode 100644 index 00000000..9e07b0d4 --- /dev/null +++ b/langs/tr/guides/directory.json @@ -0,0 +1,42 @@ +[ + { + "resource": "getting-started", + "title": "Getting Started", + "description": "A guide for how to get started with Solid." + }, + { + "resource": "reactivity", + "title": "Reactivity", + "description": "Full rundown of Solid's reactivity." + }, + { + "resource": "rendering", + "title": "Rendering", + "description": "Discusses the different templating and rendering options in Solid." + }, + { + "resource": "server", + "title": "Server", + "description": "An explanation of Solid's server-side capabilities." + }, + { + "resource": "typescript", + "title": "TypeScript", + "description": "Tips for using Solid with TypeScript" + }, + { + "resource": "testing", + "title": "Testing Solid", + "description": "How to test your Solid app" + }, + { + "resource": "comparison", + "title": "Comparison", + "description": "Comparisons of Solid against other frameworks." + }, + { + "resource": "faq", + "title": "FAQ", + "description": "Frequently asked questions from the community." + } +] diff --git a/langs/tr/guides/faq.md b/langs/tr/guides/faq.md new file mode 100644 index 00000000..d67383b9 --- /dev/null +++ b/langs/tr/guides/faq.md @@ -0,0 +1,132 @@ +# FAQ + +### JSX without a virtual DOM? Is this vaporware? I've heard prominent voices say that this isn't possible. + +It is possible when you don't have React's update model. JSX is a template language like those in Svelte or Vue—just one that is more flexible in certain ways. Inserting arbitrary JavaScript can be challenging at times, but no different than supporting spread operators. So, no: this isn't vaporware, but an approach proven to be one of the most performant. + +The real benefit comes in how extensible it is. We have a compiler working for you to give you optimal native DOM updates, but you have all the freedom of a library like React. You can write components using standard techniques like [render props](https://reactjs.org/docs/render-props.html) and higher order components along side your reactive "hooks". Don't like how Solid's control flow works? Write your own. + +### How is Solid so performant? + +We wish we could point to a single thing, but it really is the combination of several important design decisions: + +1. Explicit reactivity, so only the things that should be reactive are tracked. +2. Compilation with initial creation in mind. Solid uses heuristics and combines the right expressions to reduce the number of computations, but keep key updates granular and performant. +3. Reactive expressions are just functions. This enables "vanishing components" with lazy prop evaluation removing unnecessary wrappers and synchronization overhead. + +These are currently unique techniques in a combination that gives Solid an edge over the competition. + +### Is there React-Compat, or some way to use my React libraries in Solid? + +No. And there likely never will be. While the APIs are similar and components often can be moved across with minor edits, the update model is fundamentally different. React Components render over and over so code outside of Hooks works very differently. The closures and hook rules are not only unnecessary in Solid: they can prescribe code that does not work here. + +Vue-Compat, on the other hand, would be doable, although there are no plans to implement it currently. + +On the other hand, it is possible to run Solid _within_ React. [React Solid State](https://github.com/solidjs/react-solid-state) makes the Solid API accessible in React function components. [reactjs-solidjs-bridge](https://github.com/Sawtaytoes/reactjs-solidjs-bridge) lets you render React components within Solid components and vice versa, which is useful when gradually porting an app. + +### Why shouldn't I use `map` in my template, and what's the difference between `` and ``? + +If your array is static, there's nothing wrong with using map. But if you're looping over a signal or reactive property, `map` is inefficient: if the array changes for any reason, _the entire map_ will rerun and all of the nodes will be recreated. + +`` and `` both provide a loop solution that is smarter than this. They couple each rendered node with an element in the array, so when an array element changes, only the corresponding node will rerender. + +`` will do this _by index_: each node corresponds to an index in the array; `` will do this _by value_: each node corresponds to a piece of data in the array. This is why, in the callback, `` gives you a signal for the item: the index for each item is considered fixed, but the data at that index can change. On the other hand, `` gives you a signal for the index: the content of the item is considered fixed, but it can move around if elements get moved in the array. + +For example, if two elements in the array are swapped, `` will reposition the two corresponding DOM nodes and update their `index()` signals along the way. `` won't reposition any DOM nodes, but will update the `item()` signals for the two DOM nodes and cause them to rerender. + +For an in-depth demonstration of the difference, see [this segment](https://www.youtube.com/watch?v=YxroH_MXuhw&t=2164s) of Ryan's stream. + +### Why do I lose reactivity when I destructure props? + +With a props object, reactivity is enabled by tracking on property access. +If you access the property within a _tracking scope_ +like a JSX expression or an effect, then the JSX expression will rerender or the effect will rerun when that property changes. + +When you destructure, you access the properties of the object. If this takes place outside of a tracking scope, Solid won't track and rerun +your code. + +In this example, the property access happens within the JSX template, so it's +tracked and the span contents update when the signal changes: + +```jsx +function BlueText(props) { + return ( + {props.text} + ); +} +... + +``` + +But neither of these examples will update the span text because the property access happens +outside of the template: + +```jsx +function BlueText(props) { + const text = props.text; + return ( + {text} + ); +} +... + +``` + +```jsx +function BlueText({text}) { + return ( + {text} + ); +} +... + +``` + +If you prefer the style of early destructuring, though, there are two different Babel +transforms you can use to make (certain styles of) destructuring reactive +again: [babel-plugin-solid-undestructure](https://github.com/orenelbaum/babel-plugin-solid-undestructure) +and [Solid Labels'](https://github.com/LXSMNSYC/solid-labels) [object features](https://github.com/LXSMNSYC/solid-labels/blob/main/docs/ctf.md#objects). + +### Why isn't my `onChange` event handler firing on time? + +In some frameworks, the `onChange` event for inputs is modified so that it fires on every key press. But this isn't how the `onChange` event [works natively](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onchange): it is meant to reflect a _committed_ change to the input and will usually fire when the input loses focus. To handle all changes to the value of an input, use `onInput`. + +### Can you add support for class components? I find the lifecycles are easier to reason about. + +We don't intend to support class components. The lifecycles of components in Solid are tied to the scheduling of the reactive system and are artificial. You could make a class out of it, but effectively all of the non-event handler code would be run in the constructor, including the render function. It's just more syntax for an excuse to make your data less granular. + +Group data and its behaviors together, rather than lifecycles. This is a reactive best practice that has worked for decades. + +### I really dislike JSX, any chance of a different template language? Oh, I see you have Tagged Template Literals/HyperScript. Maybe I will use those... + +We use JSX the way Svelte uses their templates, to create optimized DOM instructions. The Tagged Template Literal and HyperScript solutions may be really impressive in their own right, but unless you have a real reason like a no-build requirement they are inferior in every way. Larger bundles, slower performance, and the need for manual workaround wrapping values. + +It's good to have options, but Solid's JSX is really the best solution here. A Template DSL would be great as well, albeit more restrictive, but JSX gives us so much for free. Existing Parsers, Syntax Highlighting, Prettier, Code Completion, and last but not least TypeScript. + +Other libraries have been adding support for these features but that has been an enormous effort and is still imperfect and a constant maintenance headache. This is really taking a pragmatic stance. + +### When do I use a Signal vs Store? Why are these different? + +Stores automatically wrap nested values making it ideal for deep data structures, and for things like models. For most other things Signals are lightweight and do the job wonderfully. + +As much we would love to wrap these together as a single thing, you can't proxy primitive values, so in this case we use functions. Any reactive expression (including state access) can be wrapped in a function on transport, so this provides a universal API. You can name your signals and state as you choose and it stays minimal. Last thing we'd want to do is force typing `.get()` `.set()` on the end-user or even worse `.value`. At least the former can be aliased for brevity, whereas the latter is just the least terse way to call a function. + +### Why can I not just assign a value to Solid's Store as I can in Vue, Svelte, or MobX? Where is the 2-way binding? + +Reactivity is a powerful tool but also a dangerous one. MobX knows this and introduced Strict mode and Actions to limit where/when updates occur. In Solid, which deals with whole Component trees of data, it became apparent that we can learn something from React here. You don't need to be actually immutable as long as you provide the means to have the same contract. + +Being able to pass the ability to update state is arguably even more important than deciding to pass the state. So being able to separate it is important, and only possible if reading is immutable. We also don't need to pay the cost of immutability if we can still granularly update. Luckily there are tons of prior art here between ImmutableJS and Immer. Ironically Solid acts mostly as a reverse Immer with its mutable internals and immutable interface. + +### Can I use Solid's reactivity on its own? + +Of course. While we haven't exported a standalone package it is easy to install Solid without the compiler and just use the reactive primitives. One of the benefits of granular reactivity is it is library agnostic. For that matter, almost every reactive library works this way. That is what inspired [Solid](https://github.com/solidjs/solid) and its underlying [DOM Expressions library](https://github.com/ryansolid/dom-expressions) in the first place to make a renderer purely from the reactive system. + +To list a few to try: [Solid](https://github.com/solidjs/solid), [MobX](https://github.com/mobxjs/mobx), [Knockout](https://github.com/knockout/knockout), [Svelte](https://github.com/sveltejs/svelte), [S.js](https://github.com/adamhaile/S), [CellX](https://github.com/Riim/cellx), [Derivable](https://github.com/ds300/derivablejs), [Sinuous](https://github.com/luwes/sinuous), and even recently [Vue](https://github.com/vuejs/vue). Much more goes into making a reactive library than tagging it onto a renderer like, [lit-html](https://github.com/Polymer/lit-html) for example, but it's a good way to get a feel. + +### Does Solid have a Next.js or Material Components like library I can use? + +We're working on [SolidStart](https://github.com/solidjs/solid-start), which is our SSR starter solution similar to Next.js or SvelteKit. + +For component libraries, we've got [SUID](https://suid.io/) for Material, [Hope UI](https://hope-ui.com/) for a Chakra-like solution, [Solid Bootstrap](https://solid-libs.github.io/solid-bootstrap/) and plenty more! Check out our [rapidly growing ecosystem of libraries and tools](https://www.solidjs.com/ecosystem). + +If you are interested in building your own ecosystem tool, we are readily available on our [Discord](https://discord.com/invite/solidjs), where you can join existing ecosystem efforts or start your own. diff --git a/langs/tr/guides/getting-started.md b/langs/tr/guides/getting-started.md new file mode 100644 index 00000000..6f8e39b9 --- /dev/null +++ b/langs/tr/guides/getting-started.md @@ -0,0 +1,170 @@ +# Getting Started + +**We're working on new docs.** You can check out our new beginner tutorial [here](https://docs.solidjs.com/tutorials/getting-started-with-solid/), and join our efforts on [Discord!](http://discord.com/invite/solidjs) + +## See Solid + +For quick video overviews of Solid's core concepts, check out: + +- [Solid in 100 seconds](https://youtu.be/hw3Bx5vxKl0) +- [Solid reactivity in 10 minutes](https://youtu.be/J70HXl1KhWE) + +## Try Solid + +By far the easiest way to get started with Solid is to try it online. Our REPL at https://playground.solidjs.com is the perfect way to try out ideas. As is https://codesandbox.io/ where you can modify any of [our Examples](https://github.com/solidjs/solid/blob/main/documentation/resources/examples.md). + +Alternatively, you can use our [Vite templates](https://github.com/solidjs/templates) by running these commands in your terminal: + +```sh +> npx degit solidjs/templates/js my-app +> cd my-app +> npm i # or yarn or pnpm +> npm run dev # or yarn or pnpm +``` + +Or for TypeScript: + +```sh +> npx degit solidjs/templates/ts my-app +> cd my-app +> npm i # or yarn or pnpm +> npm run dev # or yarn or pnpm +``` + +Or you can install the dependencies in your own project. To use Solid with JSX +(recommended), you need to install the `solid-js` NPM library and the +[Solid JSX compiler](https://github.com/ryansolid/dom-expressions/tree/main/packages/babel-plugin-jsx-dom-expressions) +Babel plugin: + +```sh +> npm install solid-js babel-preset-solid +``` + +Then add `babel-preset-solid` to your `.babelrc`, or to your Babel config in webpack or rollup: + +```json +"presets": ["solid"] +``` + +For TypeScript, set your `tsconfig.json` to handle Solid's JSX as follows +(see the [TypeScript guide](https://www.solidjs.com/guides/typescript) +for more details): + +```json +"compilerOptions": { + "jsx": "preserve", + "jsxImportSource": "solid-js", +} +``` + +## Learn Solid + +Solid is all about small composable pieces that serve as building blocks for applications. These pieces are mostly functions which make up many shallow top-level APIs. Fortunately, you won't need to know about most of them to get started. + +The two main types of building blocks you have at your disposal are Components and Reactive Primitives. + +Components are functions that accept a props object and return JSX elements including native DOM elements and other components. They can be expressed as JSX Elements in PascalCase: + +```jsx +function MyComponent(props) { + return
    Hello {props.name}
    ; +} + +; +``` + +Components are lightweight in that they are not stateful themselves and have no instances. Instead, they serve as factory functions for DOM elements and reactive primitives. + +Solid's fine-grained reactivity is built on three core primitives: Signals, Memos, and Effects. Together, they form an auto-tracking synchronization engine that ensures your view stays up to date. Reactive computations take the form of function-wrapped expressions that execute synchronously. + +```js +const [first, setFirst] = createSignal("JSON"); +const [last, setLast] = createSignal("Bourne"); + +createEffect(() => console.log(`${first()} ${last()}`)); +``` + +You can learn more about [Solid's Reactivity](/guides/reactivity) and [Solid's Rendering](/guides/rendering). + +## Think Solid + +Solid's design carries several opinions on what principles and values help us best build websites and applications. It is easier to learn and use Solid when you are aware of the philosophy behind it. + +### 1. Declarative Data + +Declarative data is the practice of tying the description of data’s behavior to its declaration. This allows for easy composition by packaging all aspects of data’s behavior in a single place. + +### 2. Vanishing Components + +It's hard enough to structure your components without taking updates into consideration. Solid updates are completely independent of the components. Component functions are called once and then cease to exist. Components exist to organize your code and not much else. + +### 3. Read/Write segregation + +Precise control and predictability make for better systems. We don't need true immutability to enforce unidirectional flow, just the ability to make the conscious decision which consumers may write and which may not. + +### 4. Simple is better than easy + +A lesson that comes hard for fine-grained reactivity. Explicit and consistent conventions even if they require more effort are worth it. The aim is to provide minimal tools to serve as the basis to build upon. + +## Web Components + +Solid was born with the desire to have Web Components as first class citizens. Over time its design has evolved and goals have changed. However, Solid is still a great way to author Web Components. [Solid Element](https://github.com/solidjs/solid/tree/main/packages/solid-element) allows you to write and wrap Solid's function components to produce small and performant Web Components. Inside Solid apps Solid Element is able to still leverage Solid's Context API, and Solid's Portals support Shadow DOM isolated styling. + +## Server Rendering + +Solid has a dynamic server side rendering solution that enables a truly isomorphic development experience. Through the use of our Resource primitive, async data requests are easily made and, more importantly, automatically serialized and synchronized between client and browser. + +Since Solid supports asynchronous and stream rendering on the server, you get to write your code one way and have it execute on the server. This means that features like [render-as-you-fetch](https://reactjs.org/docs/concurrent-mode-suspense.html#approach-3-render-as-you-fetch-using-suspense) and code splitting just work in Solid. + +For more information, read the [Server guide](/guides/server#server-side-rendering). + +## Buildless options + +If you need or prefer to use Solid in non-compiled environments such as plain HTML files, https://codepen.io, etc, you can use [` html`` ` Tagged Template Literals](https://github.com/solidjs/solid/tree/main/packages/solid/html) or [HyperScript `h()` functions](https://github.com/solidjs/solid/tree/main/packages/solid/h) in plain JavaScript instead of Solid's compile-time-optimized JSX syntax. + +You can run them straight from the browser using [Skypack](https://www.skypack.dev/), for example: + +```html + + + + + +``` + +The advantages of going buildless come with tradeoffs: + +- Expressions need to always be a wrapped in a getter function or they won't be reactive. + The following will not update when the `first` or `last` values change because the values are not being accessed inside an effect that the template creates internally, therefore dependencies will not be tracked: + ```js + html`

    Hello ${first() + " " + last()}

    `; + // or + h("h1", {}, "Hello ", first() + " " + last()); + ``` + The following will update as expected when `first` or `last` change because the template will read from the getter within an effect and dependencies will be tracked: + ```js + html`

    Hello ${() => first() + " " + last()}

    `; + // or + h("h1", {}, "Hello ", () => first() + " " + last()); + ``` + Solid's JSX doesn't have this issue because of its compile-time abilities, and an expression like `

    Hello {first() + ' ' + last()}

    ` will be reactive. +- Build-time optimizations won't be in place like they are with Solid JSX, meaning app startup speed will be slightly slower because each template gets compiled at runtime the first time it is executed, but for many use cases this perf hit is imperceivable. Ongoing speed after startup will remain the same with the ` html`` ` template tag as with JSX. `h()` calls will always have slower ongoing speed due to their inability to statically analyze whole templates before being executed. + +You need the corresponding DOM Expressions library for these to work with TypeScript. You can use Tagged Template Literals with [Lit DOM Expressions](https://github.com/ryansolid/dom-expressions/tree/main/packages/lit-dom-expressions) or HyperScript with [Hyper DOM Expressions](https://github.com/ryansolid/dom-expressions/tree/main/packages/hyper-dom-expressions). diff --git a/langs/tr/guides/reactivity.md b/langs/tr/guides/reactivity.md new file mode 100644 index 00000000..bb3da055 --- /dev/null +++ b/langs/tr/guides/reactivity.md @@ -0,0 +1,95 @@ +# Reactivity + +Solid's data management is built off a set of flexible reactive primitives which are responsible for all the updates. It takes a very similar approach to MobX or Vue except it never trades its granularity for a VDOM. Dependencies are automatically tracked when you access your reactive values in your Effects and JSX View code. + +Solid's primitives come in the form of `create` calls that often return tuples, where generally the first element is a readable primitive and the second is a setter. It is common to refer to only the readable part by the primitive name. + +Here is a basic auto incrementing counter that is updating based on setting the `count` signal. + +```jsx +import { createSignal, onCleanup } from "solid-js"; +import { render } from "solid-js/web"; + +const App = () => { + const [count, setCount] = createSignal(0), + timer = setInterval(() => setCount(count() + 1), 1000); + onCleanup(() => clearInterval(timer)); + + return
    {count()}
    ; +}; + +render(() => , document.getElementById("app")); +``` + +## Introducing Primitives + +Solid is made up of 3 primary primitives: Signal, Memo, and Effect. At their core is the Observer pattern where Signals (and Memos) are tracked by wrapping Memos and Effects. + +Signals are the most core primitive. They contain value, and get and set functions so we can intercept when they are read and written to. + +```js +const [count, setCount] = createSignal(0); +``` + +Effects are functions that wrap reads of our signal and re-execute whenever a dependent Signal's value changes. This is useful for creating side effects, like rendering. + +```js +createEffect(() => console.log("The latest count is", count())); +``` + +Finally, Memos are cached derived values. They share the properties of both Signals and Effects. They track their own dependent Signals, re-executing only when those change, and are trackable Signals themselves. + +```js +const fullName = createMemo(() => `${firstName()} ${lastName()}`); +``` + +## How it Works + +Signals are event emitters that hold a list of subscriptions. They notify their subscribers whenever their value changes. + +Where things get more interesting is how these subscriptions happen. Solid uses automatic dependency tracking. Updates happen automatically as the data changes. + +The trick is a global stack at runtime. Before an Effect or Memo executes (or re-executes) its developer-provided function, it pushes itself on to that stack. Then any Signal that is read checks if there is a current listener on the stack and if so adds the listener to its subscriptions. + +You can think of it like this: + +```js +function createSignal(value) { + const subscribers = new Set(); + + const read = () => { + const listener = getCurrentListener(); + if (listener) subscribers.add(listener); + return value; + }; + + const write = (nextValue) => { + value = nextValue; + for (const sub of subscribers) sub.run(); + }; + + return [read, write]; +} +``` + +Now whenever we update the Signal we know which Effects to re-run. Simple yet effective. The actual implementation is much more complicated but that is the guts of what is going on. + +For more detailed understanding of how Reactivity works these are useful articles: + +[A Hands-on Introduction to Fine-Grained Reactivity](https://dev.to/ryansolid/a-hands-on-introduction-to-fine-grained-reactivity-3ndf) + +[Building a Reactive Library from Scratch](https://dev.to/ryansolid/building-a-reactive-library-from-scratch-1i0p) + +[SolidJS: Reactivity to Rendering](https://indepth.dev/posts/1289/solidjs-reactivity-to-rendering) + +## Considerations + +This approach to reactivity is very powerful and dynamic. It can handle dependencies changing on the fly through executing different branches of conditional code. It also works through many levels of indirection. Any function executed inside a tracking scope is also being tracked. + +However, there are some key behaviors and tradeoffs we must be aware of. + +1. All reactivity is tracked from function calls whether directly or hidden beneath getter/proxy and triggered by property access. This means where you access properties on reactive objects is important. + +2. Components and callbacks from control flows are not tracking scopes and only execute once. This means destructuring or doing logic top-level in your components will not re-execute. You must access these Signals, Stores, and props from within other reactive primitives or the JSX for that part of the code to re-evaluate. + +3. This approach only tracks synchronously. If you have a setTimeout or use an async function in your Effect the code that executes async after the fact won't be tracked. diff --git a/langs/tr/guides/rendering.md b/langs/tr/guides/rendering.md new file mode 100644 index 00000000..a330dee1 --- /dev/null +++ b/langs/tr/guides/rendering.md @@ -0,0 +1,282 @@ +# Rendering + +Solid supports templating in 3 forms JSX, Tagged Template Literals and Solid's HyperScript variant, although JSX is the predominate form. Why? JSX is a great DSL made for compilation. It has clear syntax, supports TypeScript, works with Babel and supports other tooling like Code Syntax Highlighting and Prettier. It was only pragmatic to use a tool that basically gives you that all for free. As a compiled solution it provides great DX. Why struggle with custom Syntax DSLs when you can use one so widely supported? + +## JSX Compilation + +Rendering involves precompilation of JSX templates into optimized native js code. The JSX code constructs: + +- Template DOM elements which are cloned on each instantiation +- A series of reference declarations using only firstChild and nextSibling +- Fine grained computations to update the created elements. + +This approach is both more performant and produces less code than creating each element, one by one, with document.createElement. + +## Attributes and Props + +Solid attempts to reflect HTML conventions as much as possible including case insensitivity of attributes. + +The majority of all attributes on native element JSX are set as DOM attributes. Static values are built right into the template that is cloned. There are a number of exceptions like `class`, `style`, `value`, `innerHTML` which provide extra functionality. + +However, custom elements (with exception of native built-ins) default to properties when dynamic. This is to handle more complex data types. It does this conversion by camel casing standard snake case attribute names `some-attr` to `someAttr`. + +However, it is possible to control this behavior directly with namespace directives. You can force an attribute with `attr:` or force prop `prop:` + +```jsx + +``` + +> **Note:** Static attributes are created as part of the html template that is cloned. Expressions fixed and dynamic are applied afterwards in JSX binding order. While this is fine for most DOM elements there are some, like input elements with `type='range'`, where order matters. Keep this in mind when binding elements. + +## Entry + +The easiest way to mount Solid is to import render from 'solid-js/web'. `render` takes a function as the first argument and the mounting container for the second and returns a disposal method. This `render` automatically creates the reactive root and handles rendering into the mount container. For best performance use an element with no children. + +```jsx +import { render } from "solid-js/web"; + +render(() => , document.getElementById("main")); +``` + +> **Important** The first argument needs to be a function. Otherwise we can't properly track and schedule the reactive system. Omitting the function wrapper will cause your Effects not to run. + +## Components + +Components in Solid are just Pascal (Capital) cased functions. Their first argument is a props object and they return real DOM nodes. + +```jsx +const Parent = () => ( +
    + +
    +); + +const Label = (props) => ( + <> +
    {props.greeting}
    + {props.children} + +); +``` + +Since all JSX nodes are actual DOM nodes, the only responsibility of top level Components is to append them to the DOM. + +## Props + +Much like React, Vue, Angular and other frameworks, Solid allows you to define properties on your components to pass data to child components. Here a parent is passing the string "Hello" to the `Label` component via a `greeting` property. + +```jsx +const Parent = () => ( +
    + +
    +); +``` + +In the above example, the value set on `greeting` is static, but we can also set dynamic values. For example: + +```jsx +const Parent = () => { + const [greeting, setGreeting] = createSignal("Hello"); + + return ( +
    + +
    + ); +}; +``` + +Components can access properties passed to them via a `props` argument. + +```jsx +const Label = (props) => ( + <> +
    {props.greeting}
    + {props.children} + +); +``` + +Unlike in some other frameworks, you cannot use object destructuring on the `props` of a component. This is because the `props` object, behind the scenes, relies on Object getters to lazily retrieve values. Using object destructuring breaks the reactivity of `props`. + +This example shows the "correct" way of accessing props in Solid: + +```jsx +// Here, `props.name` will update like you'd expect +const MyComponent = (props) =>
    {props.name}
    ; +``` + +This example shows the wrong way of accessing props in Solid: + +```jsx +// This is bad +// Here, `props.name` will not update (i.e. is not reactive) as it is destructured into `name` +const MyComponent = ({ name }) =>
    {name}
    ; +``` + +While the props object looks like a normal object when you use it (and TypeScript users will note that it is typed like a normal object), in reality it is reactive – somewhat similar to a Signal. This has a few implications. + +Because unlike most JSX frameworks, Solid's function components are only executed once (rather than every render cycle), the following example will not work as expected. + +```jsx +import { createSignal } from "solid-js"; + +const BasicComponent = (props) => { + const value = props.value || "default"; + + return
    {value}
    ; +}; + +export default function Form() { + const [value, setValue] = createSignal(""); + + return ( +
    + + setValue(e.currentTarget.value)} /> +
    + ); +} +``` + +In this example, what we probably want to happen is for the `BasicComponent` to display the current value typed into the `input`. But, as a reminder, the `BasicComponent` function will only be executed once when the component is initially created. At this time (at creation), `props.value` will equal `''`. This means that `const value` in `BasicComponent` will resolve to `'default'` and never update. While the `props` object is reactive, accessing the props in `const value = props.value || 'default';` is outside the observable scope of Solid, so it isn't automatically re-evaluated when props change. + +So how can we fix our problem? + +Well, in general, we need to access `props` somewhere that Solid can observe it. Generally this means inside JSX or inside a `createMemo`, `createEffect`, or thunk(`() => ...`). Here is one solution that works as expected: + +```jsx +const BasicComponent = (props) => { + return
    {props.value || "default"}
    ; +}; +``` + +This, equivalently, can be hoisted into a function: + +```jsx +const BasicComponent = (props) => { + const value = () => props.value || "default"; + + return
    {value()}
    ; +}; +``` + +Another option, if it is an expensive computation, is to use `createMemo`. For example: + +```jsx +const BasicComponent = (props) => { + const value = createMemo(() => props.value || "default"); + + return
    {value()}
    ; +}; +``` + +Or using a helper + +```jsx +const BasicComponent = (props) => { + props = mergeProps({ value: "default" }, props); + + return
    {props.value}
    ; +}; +``` + +As a reminder, the following examples will _not_ work: + +```jsx +// bad +const BasicComponent = (props) => { + const { value: valueProp } = props; + const value = createMemo(() => valueProp || "default"); + return
    {value()}
    ; +}; + +// bad +const BasicComponent = (props) => { + const valueProp = props.value; + const value = createMemo(() => valueProp || "default"); + return
    {value()}
    ; +}; +``` + +Solid's Components are the key part of its performance. Solid's approach of "Vanishing" Components is made possible by lazy prop evaluation. Instead of evaluating prop expressions immediately and passing in values, execution is deferred until the prop is accessed in the child. Doing so we postpone execution until the last moment, typically right in the DOM bindings, maximizing performance. This flattens the hierarchy and removes the need to maintain a tree of Components. + +```jsx +; + +// compiles roughly to: + +// we untrack the component body to isolate it and prevent costly updates +untrack(() => + Component({ + prop1: "static", + // dynamic expression so we wrap in a getter + get prop2() { + return state.dynamic; + }, + }) +); +``` + +To help maintain reactivity Solid has a couple of prop helpers: + +```jsx +// default props +props = mergeProps({ name: "Smith" }, props); + +// clone props +const newProps = mergeProps(props); + +// merge props +props = mergeProps(props, otherProps); + +// split props into multiple props objects +const [local, others] = splitProps(props, ["class"]) +
    +``` + +## Children + +Solid handles JSX Children similar to React. A single child is a single value on `props.children` and multiple children is handled via an array of values. Normally, you pass them through to the JSX view. However, if you want to interact with them the suggested method is the `children` helper which resolves any downstream control flows and returns a memo. + +```jsx +// single child +const Label = (props) =>
    Hi, { props.children }
    + + + +// multi child +const List = (props) =>
    {props.children}
    ; + + +
    First
    + {state.expression} + +
    + +// map children +const List = (props) =>
      + {item =>
    • {item}
    • }
      +
    ; + +// modify and map children using helper +const List = (props) => { + // children helper memoizes value and resolves all intermediate reactivity + const memo = children(() => props.children); + createEffect(() => { + const children = memo(); + children.forEach((c) => c.classList.add("list-child")) + }) + return
      + {item =>
    • {item}
    • }
      +
    ; +``` + +**Important:** Solid treats child tags as expensive expressions and wraps them the same way as dynamic reactive expressions. This means they evaluate lazily on `prop` access. Be careful accessing them multiple times or destructuring before the place you would use them in the view. This is because Solid doesn't have the luxury of creating Virtual DOM nodes ahead of time and then diffing them, so resolution of these `props` must be lazy and deliberate. Use `children` helper if you wish to do this as it memoizes them. diff --git a/langs/tr/guides/server.md b/langs/tr/guides/server.md new file mode 100644 index 00000000..4d3d64b6 --- /dev/null +++ b/langs/tr/guides/server.md @@ -0,0 +1,140 @@ +# Server Side Rendering + +Solid handles Server rendering by compiling JSX templates to ultra efficient string appending code. This can be achieved through the babel plugin or preset by passing in `generate: "ssr"`. For both client and server you need to pass in `hydratable: true` to generate the hydration compatible code. + +The `solid-js` and `solid-js/web` runtimes are swapped for non-reactive counterparts when running in a node environment. For other environments you will need to bundle the server code with conditional exports set to `node`. Most bundlers have a way of doing this. In general we also recommend using the `solid` export conditions as well as it is recommend that libraries ship their source under the `solid` export. + +Building for SSR definitely takes a bit more configuration because we will be generating 2 separate bundles. The client entry should use `hydrate`: + +```jsx +import { hydrate } from "solid-js/web"; + +hydrate(() => , document); +``` + +_Note: It is possible to render and hydrate from the Document root. This allows us to describe our full view in JSX._ + +The server entry can use one of the four rendering options offered by Solid. Each produces the output and a script tag to be inserted in the head of the document. + +```jsx +import { + renderToString, + renderToStringAsync, + renderToStream +} from "solid-js/web"; + +// Synchronous string rendering +const html = renderToString(() => ); + +// Asynchronous string rendering +const html = await renderToStringAsync(() => ); + +// Stream rendering +const stream = renderToStream(() => ); + +// Node +stream.pipe(res); + +// Web streams (for like Cloudflare Workers) +const { readable, writable } = new TransformStream(); +stream.pipeTo(writable); +``` + +For your convenience `solid-js/web` exports an `isServer` flag. This is useful as most bundlers will be able to treeshake anything under this flag or imports only used by code under this flag out of your client bundle. + +```jsx +import { isServer } from "solid-js/web"; + +if (isServer) { + // only do this on the server +} else { + // only do this in the browser +} +``` + +## Hydration Script + +In order to progressively hydrate even before Solid's runtime loads, a special script needs to be inserted on the page. It can either be generated and inserted via `generateHydrationScript` or included as part of the JSX using the `` tag. + +```js +import { generateHydrationScript } from "solid-js/web"; + +const app = renderToString(() => ); + +const html = ` + + + 🔥 Solid SSR 🔥 + + + + ${generateHydrationScript()} + + ${app} + +`; +``` + +```jsx +import { HydrationScript } from "solid-js/web"; + +const App = () => { + return ( + + + 🔥 Solid SSR 🔥 + + + + + + {/*... rest of App*/} + + ); +}; +``` + +When hydrating from the document, inserting assets that aren't available in the client run can also mess things up when not under the `` tag. Solid provides a `` component whose children will work as normal on the server, but not hydrate in the browser. + +```jsx + + + +``` + +## Async and Streaming SSR + +These mechanisms are built on Solid's knowledge of how your application works. +It uses Suspense and the Resource API on the server, instead of fetching ahead and then rendering. +Solid fetches as it renders on the server just like it does on the client. +Your code is written exactly the same way. + +Async rendering waits until all Suspense boundaries resolve and then sends the results (or writes them to a file in the case of Static Site Generation). + +Streaming starts flushing synchronous content to the browser immediately. Initially, it renders your Suspense fallbacks on the server and sends them to the client. +Then, as the async data finishes loading on the server, we send the data and HTML over the same stream to the client. +The browser finishes the job, resolves the Suspense, and replaces the fallback with real content. + +The advantage of this approach: + +- Server doesn't have to wait for async data to respond. Assets can start loading sooner in the browser, and the user can start seeing content sooner. +- Compared to client fetching like JAMStack, data loading starts on the server immediately and doesn't have to wait for client JavaScript to load. +- All data is serialized and transported from server to client automatically. + +## SSR Caveats + +Solid's Isomorphic SSR solution is very powerful in that you can write your code mostly as single code base that runs similarly in both environments. However there are expectations that this puts on hydration. Mostly that the rendered view in the client is the same as it would be rendered on the server. It doesn't need to be exact in terms of text, but structurally the markup should be the same. + +We use markers rendered in the server to match elements and resource locations on server. For this reason the Client and Server should have the same components. This is not typically a problem given that Solid renders the same way on client and server. But currently there is no means to render something on the server that does not get hydrated on the client. Currently, there is no way to partially hydrate a whole page, and not generate hydration markers for it. It is all or nothing. Partial Hydration is something we want to explore in the future. + +Finally, all resources need to be defined under the `render` tree. They are automatically serialized and picked up in the browser, but that works because the `render` methods keep track of the progress of the render. Something we cannot do if they are created in isolated context. Similarly there is no reactivity on the server so do not update signals on initial render and expect them to reflect higher up the tree. While we have Suspense boundaries Solid's SSR is basically top down. + +## Getting Started with SSR + +SSR configurations are tricky. We have a few examples in the [solid-ssr](https://github.com/solidjs/solid/blob/main/packages/solid-ssr) package. + +However, a new starter is in the works [SolidStart](https://github.com/solidjs/solid-start) that aims to make this experience much smoother. + +## Getting Started with Static Site Generation + +[solid-ssr](https://github.com/solidjs/solid/blob/main/packages/solid-ssr) also ships with a utility for generating static or prerendered sites. Read the README for more information. diff --git a/langs/tr/guides/testing.md b/langs/tr/guides/testing.md new file mode 100644 index 00000000..03f3eca5 --- /dev/null +++ b/langs/tr/guides/testing.md @@ -0,0 +1,431 @@ +# Testing Solid + +To use your Solid code in production, it needs to be tested. Since you don't want to test everything manually, you need automated tests. This guide describes how to set everything up and a few useful patterns for testing Solid code. + +## Testing Setup + +We offer support for two test runners: + +- jest - very well established with many features + +- uvu - only brings the bare necessities + +Both are based around [solid-testing-library](https://github.com/solidjs/solid-testing-library), which integrates [Testing Library](https://testing-library.com/) into Solid. Testing Library mimics a light-weight browser and provides an API to interact with it from your tests. + +We maintain a starter template for Solid and Jest tests. We recommend you base your project on it, or alternatively install the starter template in a scratch project and copy the configuration from it into your own project. + +The templates use the [degit](https://github.com/Rich-Harris/degit) utility for installation. + +### Setting up Jest + +The Jest integration is based around the [solid-jest/preset/browser](https://github.com/solidjs/solid-jest) Jest configuration preset which lets you use Solid as in the browser. This uses babel to transform the Solid code. + +It uses [jest-dom](https://github.com/testing-library/jest-dom) to extend `expect` with a bunch of custom matchers that help you write tests. + +#### Jest with TypeScript (`ts-jest`) + +```bash +$ npx degit solidjs/templates/ts-jest my-solid-project +$ cd my-solid-project +$ npm install # or pnpm install or yarn install +``` + +Note that this template does not do typechecks during testing; you can use your IDE or a custom `tsc --noEmit` script in `package.json` to trigger such checks. + +### Setting up uvu + +We also maintain a starter template for `uvu`. + +It includes [solid-dom-testing](https://www.npmjs.com/package/solid-dom-testing) to help you write assertions useful with Testing Library. + +#### Uvu with TypeScript (`ts-uvu`) + +```bash +$ npx degit solidjs/templates/ts-uvu my-solid-project +$ cd my-solid-project +$ npm install # or pnpm install or yarn install +``` + +#### Uvu coverage Reports + +> Unfortunately, due to a [limitation of babel](https://github.com/babel/babel/issues/4289), we cannot get source maps output for transpiled JSX, which will result in components to show zero coverage. It will work for non-JSX code, though. + +If you want to check code coverage of your tests, the favorite tool for uvu is c8. To install and set it up, run: + +```sh +> npm i --save-dev c8 # or yarn add -D or pnpm +> npm set-script "test:coverage" "c8 uvu -r solid-register" +``` + +Now if you `npm run test:coverage`, you'll see the test coverage. + +If you want nice HTML coverage reports, you can use `c8 -r html` instead of `c8` to enable the html reporter. + +#### Watch Mode + +`uvu` does not have a watch mode out of the box, but you can use `chokidar-cli` to do the same: + +```sh +> npm i --save-dev chokidar-cli # or yarn add -D or pnpm +> npm set-script "test:watch" "chokidar src/**/*.ts src/**/*.tsx -c \"uvu -r solid-register\" +# use .js/.jsx instead of .ts/.tsx +``` + +Now if you run `npm run test:watch`, the tests will run every time you change a file. + +## Testing Patterns and Best Practices + +Now that you have installed your testing tools, you should start to use them. In order to make this easier, Solid supports a few nice patterns. + +### Testing Reactive State + +You may want to keep parts of your state separate from the components for ease of maintenance or being able to support multiple views. In this case, the interface against which you are testing is the state itself. Keep in mind that out of a [reactive root](https://www.solidjs.com/docs/latest/api#createroot) your state is not tracked and updates won't trigger effects and memos. + +Also, since effects trigger asynchronously, it can help to wrap our assertions in a final effect. Alternatively, to observe a sequence of effects over multiple changes, it can help to return the necessary tools from `createRoot` and execute them in an async test function (as `createRoot` itself cannot take an `async` function). + +As an example, let's test `createLocalStorage` from the [todo example](https://www.solidjs.com/examples/todos): + +```ts +import { createEffect } from "solid-js"; +import { createStore, Store, SetStoreFunction } from "solid-js/store"; + +export function createLocalStore( + initState: T +): [Store, SetStoreFunction] { + const [state, setState] = createStore(initState); + if (localStorage.todos) setState(JSON.parse(localStorage.todos)); + createEffect(() => (localStorage.todos = JSON.stringify(state))); + return [state, setState]; +} +``` + +Instead of creating a TODO component, we can test this model in isolation; when we do that, we need to keep in mind that 1. reactive changes only work when they have a tracking context provided by `render` or `createRoot` and 2. are asynchronous, but we can use `createEffect` to catch them. Using `createRoot` has the advantage that we can trigger the disposal manually: + +#### Testing with Jest + +```ts +import { createLocalStore } from "./main.tsx"; +import { createRoot, createEffect } from "solid-js"; + +describe("createLocalStore", () => { + beforeEach(() => { + localStorage.removeItem("todos"); + }); + + const initialState = { + todos: [], + newTitle: "", + }; + + test("it reads pre-existing state from localStorage", () => + createRoot((dispose) => { + const savedState = { todos: [], newTitle: "saved" }; + localStorage.setItem("todos", JSON.stringify(savedState)); + const [state] = createLocalStore(initialState); + expect(state).toEqual(savedState); + dispose(); + })); + + test("it stores new state to localStorage", () => + createRoot((dispose) => { + const [state, setState] = createLocalStore(initialState); + setState("newTitle", "updated"); + // to catch an effect, use an effect + return new Promise((resolve) => + createEffect(() => { + expect(JSON.parse(localStorage.todos || "")).toEqual({ + todos: [], + newTitle: "updated", + }); + dispose(); + resolve(); + }) + ); + })); + + test("it updates state multiple times", async () => { + const { dispose, setState } = createRoot((dispose) => { + const [state, setState] = createLocalStore(initialState); + return { dispose, setState }; + }); + setState("newTitle", "first"); + // wait a tick to resolve all effects + await new Promise((done) => setTimeout(done, 0)); + expect(JSON.parse(localStorage.todos || "")).toEqual({ + todos: [], + newTitle: "first", + }); + setState("newTitle", "second"); + await new Promise((done) => setTimeout(done, 0)); + expect(JSON.parse(localStorage.todos || "")).toEqual({ + todos: [], + newTitle: "first", + }); + dispose(); + }); +}); +``` + +#### Testing with uvu + +```ts +import { createLocalStore } from "./main"; +import { suite } from "uvu"; +import * as assert from "uvu/assert"; +import { createEffect, createRoot } from "solid-js"; + +const todoTest = suite("createLocalStore"); + +todoTest.before.each(() => { + localStorage.removeItem("todos"); +}); + +const initialState = { + todos: [], + newTitle: "", +}; + +todoTest("it reads pre-existing state from localStorage", () => + createRoot((dispose) => { + const savedState = { todos: [], newTitle: "saved" }; + localStorage.setItem("todos", JSON.stringify(savedState)); + const [state] = createLocalStore(initialState); + assert.equal(state, savedState); + dispose(); + }) +); + +todoTest("it stores new state to localStorage", () => + createRoot((dispose) => { + const [_, setState] = createLocalStore(initialState); + setState("newTitle", "updated"); + // to catch an effect, we need an effect + return new Promise((resolve) => + createEffect(() => { + assert.equal(JSON.parse(localStorage.todos || ""), { + todos: [], + newTitle: "updated", + }); + dispose(); + resolve(); + }) + ); + }) +); + +todoTest.run(); +``` + +### Testing directives + +[Directives](https://www.solidjs.com/docs/latest/api#use%3A___) allow using refs in a reusable way. They are basically functions that follow the pattern `(ref: HTMLElement, data: Accessor) => void`. In our [directives tutorial](https://www.solidjs.com/tutorial/bindings_directives?solved), we define the `clickOutside` directive that should call the callback wrapped in the accessor argument. + +We could now create a component and use the directive in there, but then we'd be testing the use of directives instead of directly testing the directive. It's simpler to test the surface of the directive by providing a mounted node and the accessor: + +#### Testing with Jest + +```ts +// click-outside.test.ts +import clickOutside from "click-outside"; +import { createRoot } from "solid-js"; +import { fireEvent } from "solid-testing-library"; + +describe("clickOutside", () => { + const ref = document.createElement("div"); + + beforeAll(() => { + document.body.appendChild(ref); + }); + + afterAll(() => { + document.body.removeChild(ref); + }); + + test("will trigger on click outside", () => + createRoot( + (dispose) => + new Promise((resolve) => { + let clickedOutside = false; + clickOutside(ref, () => () => { + clickedOutside = true; + }); + document.body.addEventListener("click", () => { + expect(clickedOutside).toBeTruthy(); + dispose(); + resolve(); + }); + fireEvent.click(document.body); + }) + )); + + test("will not trigger on click inside", () => + createRoot( + (dispose) => + new Promise((resolve) => { + let clickedOutside = false; + clickOutside(ref, () => () => { + clickedOutside = true; + }); + ref.addEventListener("click", () => { + expect(clickedOutside).toBeFalsy(); + dispose(); + resolve(); + }); + fireEvent.click(ref); + }) + )); +}); +``` + +#### Testing with uvu + +```ts +// click-outside.test.ts +import clickOutside from "click-outside.tsx"; +import { createRoot } from "solid-js"; +import { fireEvent } from "solid-testing-library"; + +const clickTest = suite("clickOutside"); + +const ref = document.createElement("div"); + +clickTest.before(() => { + document.body.appendChild(ref); +}); + +clickTest.after(() => { + document.body.removeChild(ref); +}); + +clickTest("will trigger on click outside", () => + createRoot( + (dispose) => + new Promise((resolve) => { + let clickedOutside = false; + clickOutside(ref, () => () => { + clickedOutside = true; + }); + document.body.addEventListener("click", () => { + assert.ok(clickedOutside); + dispose(); + resolve(); + }); + fireEvent.click(document.body); + }) + ) +); + +clickTest("will not trigger on click inside", () => + createRoot( + (dispose) => + new Promise((resolve) => { + let clickedOutside = false; + clickOutside(ref, () => () => { + clickedOutside = true; + }); + ref.addEventListener("click", () => { + assert.is(clickedOutside, false); + dispose(); + resolve(); + }); + fireEvent.click(ref); + }) + ) +); + +clickTest.run(); +``` + +### Testing components + +Let's take a simple click-counter component that we want to test: + +```ts +// main.tsx +import { createSignal, Component } from "solid-js"; + +export const Counter: Component = () => { + const [count, setCount] = createSignal(0); + + return ( +
    setCount((c) => c + 1)}> + Count: {count()} +
    + ); +}; +``` + +Here we use `solid-testing-library`. It's most important helpers are `render` to render a component to the DOM in a managed way, `fireEvent` to dispatch events in a way that resembles actual user events and `screen` to provide global selectors. We also use helpful assertions added to `expect` provided by `@testing-library/jest-dom`. + +#### Testing with Jest + +```ts +// main.test.tsx +import { Counter } from "./main"; +import { cleanup, fireEvent, render, screen } from "solid-testing-library"; + +describe("Counter", () => { + afterEach(cleanup); + + test("it starts with zero", () => { + render(() => ); + const button = screen.getByRole("button"); + expect(button).toBeInTheDocument(); + expect(button).toHaveTextContent("Count: 0"); + }); + + test("it increases its value on click", async () => { + render(() => ); + const button = screen.getByRole("button"); + fireEvent.click(button); + // the event loop takes one Promise to resolve to be finished + await Promise.resolve(); + expect(button).toHaveTextContent("Count: 1"); + fireEvent.click(button); + await Promise.resolve(); + expect(button).toHaveTextContent("Count: 2"); + }); +}); +``` + +#### Testing with uvu + +```ts +// main.test.tsx +import { suite } from "uvu"; +import * as assert from "uvu/assert"; +import { Counter } from "main"; +import { fireEvent, render, screen } from "solid-testing-library"; +import { isInDocument, hasTextContent } from "solid-dom-testing"; + +const testCounter = suite("Counter"); + +testCounter.after.each(cleanup); + +testCounter("it starts with zero", () => { + const { getByRole } = render(() => ); + const button = getByRole("button"); + assert.ok(isInDocument(button), "button not in dom"); + assert.ok(hasTextContent(button, "Count: 0"), "wrong text content"); +}); + +testCounter("it increases its value on click", async () => { + render(() => ); + const button = screen.getByRole("button"); + fireEvent.click(button); + // the event loop takes one Promise to resolve to be finished + await Promise.resolve(); + assert.ok( + hasTextContent(button, "Count: 1"), + "not count 1 after first click" + ); + fireEvent.click(button); + await Promise.resolve(); + assert.ok( + hasTextContent(button, "Count: 2"), + "not count 2 after first click" + ); +}); + +testCounter.run(); +``` diff --git a/langs/tr/guides/typescript.md b/langs/tr/guides/typescript.md new file mode 100644 index 00000000..69324683 --- /dev/null +++ b/langs/tr/guides/typescript.md @@ -0,0 +1,632 @@ +# TypeScript + +Solid is designed to be easy to use with TypeScript: +its use of standard JSX makes code largely understood by TypeScript, +and it provides sophisticated built-in types for its API. +This guide covers some useful tips for working with TypeScript and +typing your Solid code. + +## Configuring TypeScript + +The [Solid starter templates](https://github.com/solidjs/templates/) +offer good starting points for +[`tsconfig.json`](https://github.com/solidjs/templates/blob/master/ts/tsconfig.json). + +Most importantly, to use TypeScript with the Solid JSX compiler, +you need to configure TypeScript to leave JSX constructs alone via +[`"jsx": "preserve"`](https://www.typescriptlang.org/tsconfig#jsx), +and tell TypeScript where the JSX types come from via +[`"jsxImportSource": "solid-js"`](https://www.typescriptlang.org/tsconfig#jsxImportSource). +So, a minimal `tsconfig.json` would look like this: + +```json +{ + "compilerOptions": { + "jsx": "preserve", + "jsxImportSource": "solid-js" + } +} +``` + +If your code base uses a mix of JSX types (e.g., some files are React +while other files are Solid), you can set the default `jsxImportSource` +in `tsconfig.json` for the majority of your code, and then +[override the `jsxImportSource` option](https://www.typescriptlang.org/tsconfig#jsxImportSource) +in specific `.tsx` files using the following pragma: + +```ts +/** @jsxImportSource solid-js */ +``` + +or + +```ts +/** @jsxImportSource react */ +``` + +## API Types + +Solid is written in TypeScript, so everything is typed out of the box. +The [API documentation](https://www.solidjs.com/docs/latest/api) details the +types for all API calls, as well as several helpful type definitions to make it +easier to refer to Solid notions when you need to specify explicit types. +Here, we explore the resulting types when using a few core primitives. + +### Signals + +`createSignal` is parameterized by the type `T` of the object stored in the +signal. For example: + +```ts +const [count, setCount] = createSignal(); +``` + +The first `createSignal` has return type `Signal`, corresponding to +the type we passed to it. This is a tuple of the getter and +setter, which each have a generic type: + +```ts +import type { Signal, Accessor, Setter } from 'solid-js'; +type Signal = [get: Accessor, set: Setter]; +``` + +In this case, the signal getter `count` has type +`Accessor`. `Accessor` is a type definition +provided by Solid, in this case equivalent to `() => number | undefined`. +The `| undefined` gets added in this example because we did not provide a +default value to `createSignal`, so the signal value indeed starts out as +`undefined`. + +The signal setter `setCount` has type `Setter`, which is a more +complicated type definition corresponding roughly to +`(value?: number | ((prev?: number) => number)) => number`, representing the +two possibilities for the passed argument: you can call `setCount` with +either a `number` or a +function taking the previous value (if there was one) and returning a `number`. + +The actual `Setter` type is more complicated, to detect accidentally passing +a function to the setter when you might have wanted to set the signal to that +function value instead of calling the function to determine the new value. +If you're getting a TypeScript error "Argument ... is not assignable to +parameter" when calling `setCount(value)`, then try wrapping the setter +argument as in `setCount(() => value)` to make sure that `value` isn't called. + +##### Defaults + +We can avoid having to explicitly provide the type of the signal when calling +`createSignal`, and avoid the `| undefined` part of the type, by providing +a default value to `createSignal`: + +```ts +const [count, setCount] = createSignal(0); +const [name, setName] = createSignal(''); +``` + +In this case, TypeScript infers that the signal types are `number` and `string` +respectively. Thus, for example, `count` obtains type `Accessor` +and `name` obtains type `Accessor` (without `| undefined`). + +### Context + +Similar to signals, +[`createContext`](https://www.solidjs.com/docs/latest/api#createcontext) +is parameterized by the type `T` of the context value. +We can provide this type explicitly: + +```ts +type Data = {count: number, name: string}; +const dataContext = createContext(); +``` + +In this case, `dataContext` has type `Context`, +causing `useContext(dataContext)` to have matching return type `Data | +undefined`. +The reason for `| undefined` is that the context might not be provided in the +ancestors of the current component, in which case `useContext` returns +`undefined`. + +If we instead provide a default value to `createContext`, we avoid the +`| undefined` part of the type, and often avoid having to explicitly specify +the type of the `createContext` as well: + +```ts +const dataContext = createContext({count: 0, name: ''}); +``` + +In this case, TypeScript infers that `dataContext` has type +`Context<{count: number, name: string}>`, which is equivalent to +`Context` (without `| undefined`). + +Another common pattern is to define a factory function that produces the +value for a context. Then we can grab the return type of that function using +TypeScript's +[`ReturnType`](https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype) +type helper, and use that to type the context: + +```ts +export const makeCountNameContext = (initialCount = 0, initialName = '') => { + const [count, setCount] = createSignal(initialCount); + const [name, setName] = createSignal(initialName); + return [{count, name}, {setCount, setName}] as const; + // `as const` forces tuple type inference +}; +type CountNameContextType = ReturnType; +export const CountNameContext = createContext(); +export const useCountNameContext = () => useContext(CountNameContext); +``` + +In this example, `CountNameContextType` corresponds to the return value of +`makeCountNameContext`: +```ts +[ + {readonly count: Accessor, readonly name: Accessor}, + {readonly setCount: Setter, readonly setName: Setter} +] +``` + +and `useCountNameContext` has type `() => CountNameContextType | undefined`. + +If you want to avoid the `undefined` possibility, you could assert that the +context is always provided when used: +```ts +export const useCountNameContext = () => useContext(CountNameContext)!; +``` + +This is a dangerous assumption; it would be safer to actually provide a +default argument to `createContext` so that the context is always +defined. + +## Component Types + +```ts +import type { JSX, Component } from 'solid-js'; +type Component

    = (props: P) => JSX.Element; +``` + +To type a basic component function, use the `Component

    ` type, +where `P` is the type of the `props` argument and should be an [object type](https://www.typescriptlang.org/docs/handbook/2/objects.html). +This will enforce that correctly typed props get passed in as attributes, +and that the return value is something that can be rendered by Solid: +a `JSX.Element` can be a DOM node, an array of `JSX.Element`s, +a function returning a `JSX.Element`, a boolean, `undefined`/`null`, etc. +Here are some examples: + +```tsx +const Counter: Component = () => { + const [count, setCount] = createSignal(0); + return ( + + ); +}; + +; // good +; // type error: no initial prop +hi // type error: no children prop + +const InitCounter: Component<{initial: number}> = (props) => { + const [count, setCount] = createSignal(props.initial); + return ( + + ); +}; + +; // good +``` + +If you want your component to take JSX children, you can either explicitly +add a type for `children` to `P`, or you can use the `ParentComponent` type +which automatically adds `children?: JSX.Element`. Alternatively, if you'd +like to declare your component with `function` instead of `const`, you can +use the `ParentProps` helper to type `props`. Some examples: + +```tsx +import { JSX, ParentComponent, ParentProps } from 'solid-js'; +type ParentProps

    = P & { children?: JSX.Element }; +type ParentComponent

    = Component>; + +// Equivalent typings: +//const CustomCounter: Component<{children?: JSX.Element}> = ... +//function CustomCounter(props: ParentProps): JSX.Element { ... +const CustomCounter: ParentComponent = (props) => { + const [count, setCount] = createSignal(0); + return ( + + ); +}; + +// Equivalent typings: +//const CustomInitCounter: Component<{initial: number, children?: JSX.Element}> = ... +//function CustomInitCounter(props: ParentProps<{initial: number}>): JSX.Element { ... +const CustomInitCounter: ParentComponent<{initial: number}> = (props) => { + const [count, setCount] = createSignal(props.initial); + return ( + + ); +}; +``` + +In the latter example, the `props` parameter automatically gets typed as +`props: ParentProps<{initial: number}>` which is equivalent to +`props: {initial: number, children?: JSX.Element}`. +(Note that, before Solid 1.4, `Component` was equivalent to `ParentComponent`.) + +Solid provides two other `Component` subtypes for dealing with `children`: + +```ts +import {JSX, FlowComponent, FlowProps, VoidComponent, VoidProps} from 'solid-js'; +type FlowProps

    = P & { children: C }; +type FlowComponent

    = Component>; +type VoidProps

    = P & { children?: never }; +type VoidComponent

    = Component>; +``` + +`VoidComponent` is for components that definitely do not support `children`. +`VoidComponent

    ` is equivalent to `Component

    ` when `P` doesn't provide +a type for `children`. + +`FlowComponent` is intended for "control flow" components like Solid's +`` and ``. Such components generally require `children` to make +sense, and sometimes have specific types for `children`, such as requiring it +to be a single function. For example: + +```tsx +const CallMeMaybe: FlowComponent<{when: boolean}, () => void> = (props) => { + createEffect(() => { + if (props.when) + props.children(); + }); + return <>{props.when ? 'Calling' : 'Not Calling'}; +}; + +; // type error: missing children +hi; // type error: children + + {() => console.log("Here's my number")} +; // good +``` + +## Event Handlers + +The namespace `JSX` offers a suite of useful types for working with HTML DOM +in particular. See the +[definition of JSX in dom-expressions](https://github.com/ryansolid/dom-expressions/blob/main/packages/dom-expressions/src/jsx.d.ts) +for all the types provided. + +One useful helper type provided by the `JSX` namespace is +`JSX.EventHandler`, +which represents a single-argument event handler for a DOM element type `T` +and event type `E`. +You can use this to type any event handlers you define outside JSX. +For example: + +```tsx +import type { JSX } from 'solid-js'; +const onInput: JSX.EventHandler = (event) => { + console.log('input changed to', event.currentTarget.value); +}; + + +``` + +Handlers defined inline within +[`on___` JSX attributes](https://www.solidjs.com/docs/latest/api#on___) +(with built-in event types) are automatically typed as the appropriate +`JSX.EventHandler`: + +```tsx + { + console.log('input changed to', event.currentTarget.value); +}}/>; +``` + +Note that `JSX.EventHandler` constrains the event's +[`currentTarget` attribute](https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget) +to be of type `T` (in the example, `event.currentTarget` is typed +as `HTMLInputEvent`, so has attribute `value`). However, the event's +[`target` attribute](https://developer.mozilla.org/en-US/docs/Web/API/Event/target) +could be any `DOMElement`. +This is because `currentTarget` is the element that the +event handler was attached to, so has a known type, whereas `target` is +whatever the user interacted with that caused the event to bubble to or get +captured by the event handler, which can be any DOM element. + +## The ref Attribute + +When we use the `ref` attribute with a variable, we tell Solid to assign the +DOM element to +the variable once the element is rendered. Without TypeScript, this looks like: + +```jsx +let divRef; + +console.log(divRef); // undefined + +onMount(() => { + console.log(divRef); //

    element +}) + +return ( +
    +) +``` + +This presents a challenge for typing that variable: should we type `divRef` +as an `HTMLDivElement`, even though it's only set as such after rendering? +(Here we assume TypeScript's `strictNullChecks` mode is turned on; +otherwise, TypeScript ignores potentially `undefined` variables.) + +The safest pattern in TypeScript is to acknowledge that `divRef` is `undefined` +for a period of time, and check when using it: + +```tsx +let divRef: HTMLDivElement | undefined; + +divRef.focus(); // correctly reported as an error at compile time + +onMount(() => { + if (!divRef) return; + divRef.focus(); // correctly allowed +}); + +return ( +
    + ... +
    +); +``` + +Alternatively, because we know `onMount` gets called only after the `
    ` +element gets rendered, we could use a +[non-null assertion (`!`)](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#non-null-assertion-operator-postfix-) +when accessing `divRef` within `onMount`: + +```tsx +onMount(() => { + divRef!.focus(); +}); +``` + +Another fairly safe pattern is to omit `undefined` from `divRef`'s type, +and use a +[definite assignment assertion (`!`)](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions) +in the `ref` attribute: + +```tsx +let divRef: HTMLDivElement; + +divRef.focus(); // correctly reported as an error at compile time + +onMount(() => { + divRef.focus(); // correctly allowed +}); + +return ( +
    + ... +
    +); +``` + +We need to use `ref={divRef!}` because TypeScript assumes that the `ref` +attribute is being set to the `divRef` variable, and thus `divRef` should +already be assigned. In Solid, it's the other way around: `divRef` gets +assigned to by the `ref` attribute. The definite assignment assertion +`divRef!` effectively convinces TypeScript that this is what's happening: +TypeScript will understand that `divRef` has been assigned after this line. + +With this pattern, TypeScript will correctly flag any accidental uses of +refs inside the body of the function (before the JSX block where they get +defined). However, TypeScript currently does not flag use of potentially +undefined variables within nested functions. In the context of Solid, +you need to take care not to use refs inside `createMemo`, `createRenderEffect`, +and `createComputed` (before the JSX block that defines the refs), +because those functions are called immediately, +so the refs won't be defined yet (yet TypeScript won't flag this as an error). +By contrast, the previous pattern would catch these errors. + +Another common, but less safe, pattern is to put the definite assignment +assertion at the point of variable declaration. + +```tsx +let divRef!: HTMLDivElement; + +divRef.focus(); // allowed despite causing an error + +onMount(() => { + divRef.focus(); // correctly allowed +}); + +return ( +
    + ... +
    +); +``` + +This approach effectively turns off assignment checking for that variable, +which is an easy workaround, but requires additional care. +In particular, unlike the previous pattern, it incorrectly allows premature +use of the variable, even outside nested functions. + +## Control Flow Narrowing + +A common pattern is to use +[``](https://www.solidjs.com/docs/latest/api#%3Cshow%3E) +to display data only when that data is defined: + +```tsx +const [name, setName] = createSignal(); + +return ( + + Hello {name().replace(/\s+/g, '\xa0')}! + +); +``` + +In this case, TypeScript can't determine that the two calls to `name()` will +return the same value, and that the second call will happen only if the first +call returned a truthy value. Thus it will complain that `name()` might be +`undefined` when trying to call `.replace()`. + +Here are two workarounds for this issue: + +1. You can manually assert that `name()` will be non-null in the second call + using TypeScript's + [non-null assertion operator `!`](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#non-null-assertion-operator-postfix-): + + ```tsx + return ( + + Hello {name()!.replace(/\s+/g, '\xa0')}! + + ); + ``` + +2. You can use the callback form of ``, which passes in the value of the + `when` prop when it is truthy: + + ```tsx + return ( + + {(n) => + <>Hello {n.replace(/\s+/g, '\xa0')}! + } + + ); + ``` + + In this case, the typing of the `Show` component is clever enough to tell + TypeScript that `n` is truthy, so it can't be `undefined` (or `null` or + `false`). + + Note, however, that this form of `` forces the entirety of the + children to render + from scratch every time `name()` changes, instead of doing this just when `name()` changes from a falsy to a truthy value. + This means that the children don't have the full benefits of fine-grained + reactivity (re-using unchanged parts and updating just what changed). + +## Special JSX Attributes and Directives + +### `on:___`/`oncapture:___` + +If you use custom event handlers via Solid's +[`on:___`/`oncapture:___` attributes](https://www.solidjs.com/docs/latest/api#on%3A___%2Foncapture%3A___), +you should define corresponding types for the resulting `Event` objects +by overriding the `CustomEvents` and `CustomCaptureEvents` interfaces +within module `"solid-js"`'s `JSX` namespace, like so: + +```tsx +class NameEvent extends CustomEvent { + type: 'Name'; + detail: {name: string}; + + constructor(name: string) { + super('Name', {detail: {name}}); + } +} + +declare module "solid-js" { + namespace JSX { + interface CustomEvents { // on:Name + "Name": NameEvent; + } + interface CustomCaptureEvents { // oncapture:Name + "Name": NameEvent; + } + } +} + +
    console.log('name is', event.detail.name)}/> +``` + +### `prop:___`/`attr:___` + +If you use forced properties via Solid's +[`prop:___` attributes](https://www.solidjs.com/docs/latest/api#prop%3A___), +or custom attributes via Solid's +[`attr:___` attributes](https://www.solidjs.com/docs/latest/api#attr%3A___), +you can define their types in the `ExplicitProperties` and +`ExplicitAttributes` interfaces, respectively: + +```tsx +declare module "solid-js" { + namespace JSX { + interface ExplicitProperties { // prop:___ + count: number; + name: string; + } + interface ExplicitAttributes { // attr:___ + count: number; + name: string; + } + } +} + + + +``` + +### `use:___` + +If you define custom directives for Solid's +[`use:___` attributes](https://www.solidjs.com/docs/latest/api#use%3A___), +you can type them in the `Directives` interface, like so: + +```tsx +function model(element: HTMLInputElement, value: Accessor>) { + const [field, setField] = value(); + createRenderEffect(() => (element.value = field())); + element.addEventListener("input", (e) => setField(e.target.value)); +} + +declare module "solid-js" { + namespace JSX { + interface Directives { // use:model + model: Signal; + } + } +} + +let [name, setName] = createSignal(''); + +; +``` + +If you're `import`ing a directive `d` from another module, and `d` is used only +as a directive `use:d`, then TypeScript (or more precisely, +[`babel-preset-typescript`](https://babeljs.io/docs/en/babel-preset-typescript)) +will by default remove the `import` of `d` (for fear that `d` is a type, +as TypeScript doesn't understand `use:d` as a reference to `d`). +There are two ways around this issue: + +1. Use + [`babel-preset-typescript`'s `onlyRemoveTypeImports: true`](https://babeljs.io/docs/en/babel-preset-typescript#onlyremovetypeimports) + configuration option, + which prevents it from removing any `import`s except for `import type ...`. + If you're using `vite-plugin-solid`, you can specify this option via + `solidPlugin({ typescript: { onlyRemoveTypeImports: true } })` + in `vite.config.ts`. + + Note that this option can be problematic if you don't vigilantly use + `export type` and `import type` throughout your codebase. + +2. Add a fake access like `false && d;` to every module `import`ing + directive `d`. + This will stop TypeScript from removing the `import` of `d`, and assuming + you're tree-shaking via e.g. [Terser](https://terser.org/), + this code will be omitted from your final code bundle. + + The simpler fake access `d;` will also prevent the `import` from being + removed, but will typically not be tree-shaken away, so will end up in + your final code bundle. diff --git a/langs/tr/tutorials/async_lazy/lesson.json b/langs/tr/tutorials/async_lazy/lesson.json new file mode 100644 index 00000000..de56f031 --- /dev/null +++ b/langs/tr/tutorials/async_lazy/lesson.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { lazy } from \"solid-js\";\n\nimport Greeting from \"./greeting\"\n\nfunction App() {\n return (\n <>\n

    Welcome

    \n \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "greeting", + "content": "export default function Greeting(props) {\n return

    Hi, {props.name}

    \n}" + } + ] +} diff --git a/langs/tr/tutorials/async_lazy/lesson.md b/langs/tr/tutorials/async_lazy/lesson.md new file mode 100644 index 00000000..af9fdf45 --- /dev/null +++ b/langs/tr/tutorials/async_lazy/lesson.md @@ -0,0 +1,20 @@ +Most bundlers (like Webpack, Rollup, Parcel, Vite) automatically handle code splitting when you use a dynamic import. Solid's `lazy` method allows us to wrap the component's dynamic import for deferred lazy loading. The output is a Component that can be used as normal in our JSX template with the exception that internally it dynamically loads the underlying imported code when it is rendered the first time, halting that branch of rendering until the code is available. + +To use `lazy`, replace the import statement: +```js +import Greeting from "./greeting"; +``` +with: +```js +const Greeting = lazy(() => import("./greeting")); +``` + +This will likely still load too quickly to see. But you add a fake delay if you wish to make the loading more visible. + +```js +const Greeting = lazy(async () => { + // simulate delay + await new Promise(r => setTimeout(r, 1000)) + return import("./greeting") +}); +``` diff --git a/langs/tr/tutorials/async_lazy/solved.json b/langs/tr/tutorials/async_lazy/solved.json new file mode 100644 index 00000000..c61a2066 --- /dev/null +++ b/langs/tr/tutorials/async_lazy/solved.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { lazy } from \"solid-js\";\n\nconst Greeting = lazy(() => import(\"./greeting\"));\n\nfunction App() {\n return (\n <>\n

    Welcome

    \n \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "greeting", + "content": "export default function Greeting(props) {\n return

    Hi, {props.name}

    \n}" + } + ] +} diff --git a/langs/tr/tutorials/async_resources/lesson.json b/langs/tr/tutorials/async_resources/lesson.json new file mode 100644 index 00000000..445c1b28 --- /dev/null +++ b/langs/tr/tutorials/async_resources/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { createSignal, createResource } from \"solid-js\";\nimport { render } from \"solid-js/web\";\n\nconst fetchUser = async (id) =>\n (await fetch(`https://swapi.dev/api/people/${id}/`)).json();\n\nconst App = () => {\n const [userId, setUserId] = createSignal();\n const [user] = createSignal();\n\n return (\n <>\n setUserId(e.currentTarget.value)}\n />\n {user.loading && \"Loading...\"}\n
    \n
    {JSON.stringify(user(), null, 2)}
    \n
    \n \n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/async_resources/lesson.md b/langs/tr/tutorials/async_resources/lesson.md new file mode 100644 index 00000000..fa6079ed --- /dev/null +++ b/langs/tr/tutorials/async_resources/lesson.md @@ -0,0 +1,19 @@ +Resources are special Signals designed specifically to handle Async loading. Their purpose is wrap async values in a way that makes them easy to interact with in Solid's distributed execution model. This is the opposite to `async`/`await` or generators which provide sequential execution models. The goal is for async to not block execution and not color our code. + +Resources can be driven by a source signal that provides the query to an async data fetcher function that returns a promise. The contents of the fetcher function can be anything. You can hit typical REST endpoints or GraphQL or anything that generates a promise. Resources are not opinionated on the means of loading the data, only that they are driven by promises. + +The resulting Resource Signal also contains reactive `loading` and `error` properties that make it easy to control our view based on the current status. + +So let's replace our user signal with a resource: +```js +const [user] = createResource(userId, fetchUser); +``` +It is driven by the `userId` Signal and calls our fetch method on change. Not much else to it. + +The second value that comes back from `createResource` contains a `mutate` method for directly updating the internal Signal and a `refetch` method to reload the current query even if the source hasn't changed. + +```js +const [user, { mutate, refetch }] = createResource(userId, fetchUser); +``` + +`lazy` uses `createResource` internally to manage its dynamic imports. diff --git a/langs/tr/tutorials/async_resources/solved.json b/langs/tr/tutorials/async_resources/solved.json new file mode 100644 index 00000000..e37ab753 --- /dev/null +++ b/langs/tr/tutorials/async_resources/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { createSignal, createResource } from \"solid-js\";\nimport { render } from \"solid-js/web\";\n\nconst fetchUser = async (id) =>\n (await fetch(`https://swapi.dev/api/people/${id}/`)).json();\n\nconst App = () => {\n const [userId, setUserId] = createSignal();\n const [user] = createResource(userId, fetchUser);\n\n return (\n <>\n setUserId(e.currentTarget.value)}\n />\n {user.loading && \"Loading...\"}\n
    \n
    {JSON.stringify(user(), null, 2)}
    \n
    \n \n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/async_suspense/lesson.json b/langs/tr/tutorials/async_suspense/lesson.json new file mode 100644 index 00000000..6779e6fb --- /dev/null +++ b/langs/tr/tutorials/async_suspense/lesson.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { lazy, Suspense } from \"solid-js\";\n\nconst Greeting = lazy(async () => {\n // simulate delay\n await new Promise(r => setTimeout(r, 1000))\n return import(\"./greeting\")\n});\n\nfunction App() {\n return (\n <>\n

    Welcome

    \n \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "greeting", + "content": "export default function Greeting(props) {\n return

    Hi, {props.name}

    \n}" + } + ] +} diff --git a/langs/tr/tutorials/async_suspense/lesson.md b/langs/tr/tutorials/async_suspense/lesson.md new file mode 100644 index 00000000..87159b1b --- /dev/null +++ b/langs/tr/tutorials/async_suspense/lesson.md @@ -0,0 +1,31 @@ +While `lazy` and `createResource` can be used on their own, Solid also provides a mechanism for coordinating the display of multiple async events. `Suspense` serves as a boundary that can show a fallback placeholder instead of the partially loaded content as these async events resolve. + +This can improve user experience by removing visual jank caused by too many intermediate and partial loading states. `Suspense` automatically detects any descendant async reads and acts accordingly. You can nest as many `Suspense` components as needed and only the nearest ancestor will transform to `fallback` when the `loading` state is detected. + +Let's add a `Suspense` component to our lazy loading example: + +```jsx +<> +

    Welcome

    + Loading...

    }> + +
    + +``` + +Now we have a loading placeholder. + +It's important to note that it's the read of an async derived value that triggers `Suspense`, not the async fetching itself. If a resource signal (including `lazy` components) is not read under the `Suspense` boundary, it will not suspend. + +`Suspense` in many ways is just a `Show` component that renders both branches. While `Suspense` is vital for asynchronous Server rendering, do not feel the need to jump immediately to using it for client-rendered code. Solid's fine-grained rendering has no additional cost for splitting things manually. + +```jsx +function Deferred(props) { + const [resume, setResume] = createSignal(false); + setTimeout(() => setResume(true), 0); + + return {props.children}; +} +``` + +All work in Solid is queued independently already. No need for things like Time Slicing. diff --git a/langs/tr/tutorials/async_suspense/solved.json b/langs/tr/tutorials/async_suspense/solved.json new file mode 100644 index 00000000..c43b56f0 --- /dev/null +++ b/langs/tr/tutorials/async_suspense/solved.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { lazy, Suspense } from \"solid-js\";\n\nconst Greeting = lazy(async () => {\n // simulate delay\n await new Promise(r => setTimeout(r, 1000))\n return import(\"./greeting\")\n});\n\nfunction App() {\n return (\n <>\n

    Welcome

    \n Loading...

    }>\n \n
    \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "greeting", + "content": "export default function Greeting(props) {\n return

    Hi, {props.name}

    \n}" + } + ] +} diff --git a/langs/tr/tutorials/async_suspense_list/lesson.json b/langs/tr/tutorials/async_suspense_list/lesson.json new file mode 100644 index 00000000..a627b09a --- /dev/null +++ b/langs/tr/tutorials/async_suspense_list/lesson.json @@ -0,0 +1,16 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { Suspense } from \"solid-js\";\n\nimport fetchProfileData from \"./mock-api\";\nimport ProfilePage from \"./profile\";\n\nconst App = () => {\n const { user, posts, trivia } = fetchProfileData();\n return (\n Loading...}>\n \n \n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + }, + { + "name": "profile", + "content": "import { For, Suspense, SuspenseList } from \"solid-js\";\n\nconst ProfileDetails = (props) =>

    {props.user?.name}

    ;\n\nconst ProfileTimeline = (props) => (\n
      \n {(post) =>
    • {post.text}
    • }
      \n
    \n);\n\nconst ProfileTrivia = (props) => (\n <>\n

    Fun Facts

    \n
      \n {(fact) =>
    • {fact.text}
    • }
      \n
    \n \n);\n\nconst ProfilePage = (props) => (\n <>\n \n Loading posts...}>\n \n \n Loading fun facts...}>\n \n \n \n);\n\nexport default ProfilePage;" + }, + { + "name": "mock-api", + "content": "import { createResource } from \"solid-js\";\n\nexport default function fetchProfileData() {\n const [user] = createResource(fetchUser);\n const [posts] = createResource(fetchPosts);\n const [trivia] = createResource(fetchTrivia);\n return { user, posts, trivia };\n}\n\nfunction fetchUser() {\n console.log(\"fetch user...\");\n return new Promise((resolve) => {\n setTimeout(() => {\n console.log(\"fetched user\");\n resolve({\n name: \"Ringo Starr\"\n });\n }, 500);\n });\n}\n\nlet ringoPosts = [\n {\n id: 0,\n text: \"I get by with a little help from my friends\"\n },\n {\n id: 1,\n text: \"I'd like to be under the sea in an octupus's garden\"\n },\n {\n id: 2,\n text: \"You got that sand all over your feet\"\n }\n];\n\nfunction fetchPosts() {\n let ringoPostsAtTheTime = ringoPosts;\n console.log(\"fetch posts...\");\n return new Promise((resolve) => {\n setTimeout(() => {\n console.log(\"fetched posts\");\n resolve(ringoPostsAtTheTime);\n }, 3000 * Math.random());\n });\n}\n\nfunction fetchTrivia() {\n console.log(\"fetch trivia...\");\n return new Promise((resolve) => {\n setTimeout(() => {\n console.log(\"fetched trivia\");\n resolve([\n {\n id: 1,\n text:\n 'The nickname \"Ringo\" came from his habit of wearing numerous rings.'\n },\n {\n id: 2,\n text: \"Plays the drums left-handed with a right-handed drum set.\"\n },\n {\n id: 3,\n text: \"Nominated for one Daytime Emmy Award, but did not win\"\n }\n ]);\n }, 3000 * Math.random());\n });\n}\n" + } + ] +} diff --git a/langs/tr/tutorials/async_suspense_list/lesson.md b/langs/tr/tutorials/async_suspense_list/lesson.md new file mode 100644 index 00000000..ef7a656b --- /dev/null +++ b/langs/tr/tutorials/async_suspense_list/lesson.md @@ -0,0 +1,17 @@ +Sometimes you have multiple `Suspense` Components that you want to coordinate. One possible approach is to put everything under a single `Suspense`, but that limits us to a single loading behavior. A single fallback state means that everything always needs to wait until the last thing is loaded. Instead, Solid introduces the `SuspenseList` Component to coordinate that. + +Consider having multiple `Suspense` components like our example. If we wrap them with a `SuspenseList` configured with `revealOrder` of `forwards`, they will render in the order they appear in the tree regardless of the order they load. This reduces the page jumping around. You can set `revealOrder` to `backwards` or `together`, which, respectively, reverses the order or waits for all Suspense Components to load. In addition there is a `tail` option that can be set to `hidden` or `collapsed`. This overrides the default behavior of showing all fallbacks with either showing none or showing the next one in the direction set by `revealOrder`. + +Our example currently is a bit of a mess in terms of loading placeholders. While it loads all the data independently we are often showing multiple placeholders depending on the order data loads in. Let's wrap our `ProfilePage` component's JSX in a ``: + +```jsx + + + Loading posts...}> + + + Loading fun facts...}> + + + +``` diff --git a/langs/tr/tutorials/async_suspense_list/solved.json b/langs/tr/tutorials/async_suspense_list/solved.json new file mode 100644 index 00000000..4df03067 --- /dev/null +++ b/langs/tr/tutorials/async_suspense_list/solved.json @@ -0,0 +1,16 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { Suspense } from \"solid-js\";\n\nimport fetchProfileData from \"./mock-api\";\nimport ProfilePage from \"./profile\";\n\nconst App = () => {\n const { user, posts, trivia } = fetchProfileData();\n return (\n Loading...}>\n \n \n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + }, + { + "name": "profile", + "content": "import { For, Suspense, SuspenseList } from \"solid-js\";\n\nconst ProfileDetails = (props) =>

    {props.user?.name}

    ;\n\nconst ProfileTimeline = (props) => (\n
      \n {(post) =>
    • {post.text}
    • }
      \n
    \n);\n\nconst ProfileTrivia = (props) => (\n <>\n

    Fun Facts

    \n
      \n {(fact) =>
    • {fact.text}
    • }
      \n
    \n \n);\n\nconst ProfilePage = (props) => (\n \n \n Loading posts...}>\n \n \n Loading fun facts...}>\n \n \n \n);\n\nexport default ProfilePage;" + }, + { + "name": "mock-api", + "content": "import { createResource } from \"solid-js\";\n\nexport default function fetchProfileData() {\n const [user] = createResource(fetchUser);\n const [posts] = createResource(fetchPosts);\n const [trivia] = createResource(fetchTrivia);\n return { user, posts, trivia };\n}\n\nfunction fetchUser() {\n console.log(\"fetch user...\");\n return new Promise((resolve) => {\n setTimeout(() => {\n console.log(\"fetched user\");\n resolve({\n name: \"Ringo Starr\"\n });\n }, 500);\n });\n}\n\nlet ringoPosts = [\n {\n id: 0,\n text: \"I get by with a little help from my friends\"\n },\n {\n id: 1,\n text: \"I'd like to be under the sea in an octupus's garden\"\n },\n {\n id: 2,\n text: \"You got that sand all over your feet\"\n }\n];\n\nfunction fetchPosts() {\n let ringoPostsAtTheTime = ringoPosts;\n console.log(\"fetch posts...\");\n return new Promise((resolve) => {\n setTimeout(() => {\n console.log(\"fetched posts\");\n resolve(ringoPostsAtTheTime);\n }, 3000 * Math.random());\n });\n}\n\nfunction fetchTrivia() {\n console.log(\"fetch trivia...\");\n return new Promise((resolve) => {\n setTimeout(() => {\n console.log(\"fetched trivia\");\n resolve([\n {\n id: 1,\n text:\n 'The nickname \"Ringo\" came from his habit of wearing numerous rings.'\n },\n {\n id: 2,\n text: \"Plays the drums left-handed with a right-handed drum set.\"\n },\n {\n id: 3,\n text: \"Nominated for one Daytime Emmy Award, but did not win\"\n }\n ]);\n }, 3000 * Math.random());\n });\n}\n" + } + ] +} diff --git a/langs/tr/tutorials/async_transitions/lesson.json b/langs/tr/tutorials/async_transitions/lesson.json new file mode 100644 index 00000000..b39a168a --- /dev/null +++ b/langs/tr/tutorials/async_transitions/lesson.json @@ -0,0 +1,17 @@ +{ + "files": [ + { + "name": "main", + "content": "import { createSignal, Suspense, Switch, Match, useTransition } from \"solid-js\";\nimport { render } from \"solid-js/web\";\nimport Child from \"./child\";\n\nimport \"./styles.css\";\n\nconst App = () => {\n const [tab, setTab] = createSignal(0);\n const updateTab = (index) => () => setTab(index);\n\n return (\n <>\n
      \n
    • \n Uno\n
    • \n
    • \n Dos\n
    • \n
    • \n Tres\n
    • \n
    \n
    \n Loading...
    }>\n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + }, + { + "name": "child", + "content": "import { createResource } from \"solid-js\";\n\nconst CONTENT = {\n Uno: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`,\n Dos: `Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?`,\n Tres: `On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains.`\n};\n\nfunction createDelay() {\n return new Promise((resolve) => {\n const delay = Math.random() * 420 + 160;\n setTimeout(() => resolve(delay), delay);\n });\n}\n\nconst Child = (props) => {\n const [time] = createResource(createDelay);\n\n return (\n
    \n This content is for page \"{props.page}\" after {time()?.toFixed()}ms.\n

    {CONTENT[props.page]}

    \n
    \n );\n};\n\nexport default Child;\n" + }, + { + "name": "styles", + "type": "css", + "content": "body{\n background-color:#eee;\n}\n\n#app{\n border-radius:3px;\n border: 1px solid #e5e5e5;\n margin:15px;\n background-color:white;\n}\n\n.tab{\n padding:25px;\n font-family:sans-serif;\n color:#444;\n min-height: 400px;\n}\n\n.pending {\n transition: color .3s;\n transition-delay: .1s;\n transition-timing-function: ease-in;\n color: #aaa;\n}\n\nul.inline{\n list-style:none;\n padding: 0;\n margin-bottom:0;\n -webkit-margin-before: 0;\n -webkit-margin-after: 0;\n -webkit-margin-start: 0px;\n -webkit-margin-end: 0px;\n -webkit-padding-start: 0px;\n}\n\nul.inline li {\n display:inline-block;\n margin-left:0;\n padding:10px;\n border-bottom:2px solid #eee;\n transition: all .5s;\n font-family:sans-serif;\n font-weight: 300;\n cursor:pointer;\n color: #aaa;\n}\n\nul.inline li.selected{\n border-bottom:2px solid #337ab7;\n color:#444;\n}\n\n.loader{\n color:#aaa;\n font-size: 16px;\n font-weight: 600;\n width: 80px;\n}" + } + ] +} diff --git a/langs/tr/tutorials/async_transitions/lesson.md b/langs/tr/tutorials/async_transitions/lesson.md new file mode 100644 index 00000000..19e386f8 --- /dev/null +++ b/langs/tr/tutorials/async_transitions/lesson.md @@ -0,0 +1,22 @@ +`Suspense` allows us to show fallback content when data is loading. This is great for initial loading, but on subsequent navigation it is often worse UX to fallback to the skeleton state. + +We can avoid going back to the fallback state by leveraging `useTransition`. It provides a wrapper and a pending indicator. The wrapper puts all downstream updates in a transaction that doesn't commit until all async events complete. + +This means that when control flow is suspended, it continues to show the current branch while rendering the next off-screen. Resource reads under existing boundaries add it to the transition. However, any new nested `Suspense` components will show "fallback" if they have not completed loading before coming into view. + +Notice when you navigate in the example, we keep seeing the content disappear back to a loading placeholder. Let's add a transition in our `App` component. First, let's replace the `updateTab` function: + +```js +const [pending, start] = useTransition(); +const updateTab = (index) => () => start(() => setTab(index)); +``` + +`useTransition` returns a pending signal indicator and a method to start the transition, which we will wrap around our update. + +We should use that pending signal to give an indicator in our UI. We can add a pending class to our tab container div: + +```js +
    +``` + +And with that our tab switching should be much smoother. diff --git a/langs/tr/tutorials/async_transitions/solved.json b/langs/tr/tutorials/async_transitions/solved.json new file mode 100644 index 00000000..04b7b6bb --- /dev/null +++ b/langs/tr/tutorials/async_transitions/solved.json @@ -0,0 +1,17 @@ +{ + "files": [ + { + "name": "main", + "content": "import { createSignal, Suspense, Switch, Match, useTransition } from \"solid-js\";\nimport { render } from \"solid-js/web\";\nimport Child from \"./child\";\n\nimport \"./styles.css\";\n\nconst App = () => {\n const [tab, setTab] = createSignal(0);\n const [pending, start] = useTransition();\n const updateTab = (index) => () => start(() => setTab(index));\n\n return (\n <>\n
      \n
    • \n Uno\n
    • \n
    • \n Dos\n
    • \n
    • \n Tres\n
    • \n
    \n
    \n Loading...
    }>\n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + }, + { + "name": "child", + "content": "import { createResource } from \"solid-js\";\n\nconst CONTENT = {\n Uno: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`,\n Dos: `Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?`,\n Tres: `On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains.`\n};\n\nfunction createDelay() {\n return new Promise((resolve) => {\n const delay = Math.random() * 420 + 160;\n setTimeout(() => resolve(delay), delay);\n });\n}\n\nconst Child = (props) => {\n const [time] = createResource(createDelay);\n\n return (\n
    \n This content is for page \"{props.page}\" after {time()?.toFixed()}ms.\n

    {CONTENT[props.page]}

    \n
    \n );\n};\n\nexport default Child;\n" + }, + { + "name": "styles", + "type": "css", + "content": "body{\n background-color:#eee;\n}\n\n#app{\n border-radius:3px;\n border: 1px solid #e5e5e5;\n margin:15px;\n background-color:white;\n}\n\n.tab{\n padding:25px;\n font-family:sans-serif;\n color:#444;\n min-height: 400px;\n}\n\n.pending {\n transition: color .3s;\n transition-delay: .1s;\n transition-timing-function: ease-in;\n color: #aaa;\n}\n\nul.inline{\n list-style:none;\n padding: 0;\n margin-bottom:0;\n -webkit-margin-before: 0;\n -webkit-margin-after: 0;\n -webkit-margin-start: 0px;\n -webkit-margin-end: 0px;\n -webkit-padding-start: 0px;\n}\n\nul.inline li {\n display:inline-block;\n margin-left:0;\n padding:10px;\n border-bottom:2px solid #eee;\n transition: all .5s;\n font-family:sans-serif;\n font-weight: 300;\n cursor:pointer;\n color: #aaa;\n}\n\nul.inline li.selected{\n border-bottom:2px solid #337ab7;\n color:#444;\n}\n\n.loader{\n color:#aaa;\n font-size: 16px;\n font-weight: 600;\n width: 80px;\n}" + } + ] +} diff --git a/langs/tr/tutorials/bindings_classlist/lesson.json b/langs/tr/tutorials/bindings_classlist/lesson.json new file mode 100644 index 00000000..8114b5fe --- /dev/null +++ b/langs/tr/tutorials/bindings_classlist/lesson.json @@ -0,0 +1,13 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nimport \"./style.css\";\n\nfunction App() {\n const [current, setCurrent] = createSignal(\"foo\");\n\n return <>\n setCurrent('foo')}\n >foo\n setCurrent('bar')}\n >bar\n setCurrent('baz')}\n >baz\n ;\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "style", + "type": "css", + "content": "button {\n display: block;\n}\n\n.selected {\n background-color: #ff3e00;\n color: white;\n}" + } + ] +} diff --git a/langs/tr/tutorials/bindings_classlist/lesson.md b/langs/tr/tutorials/bindings_classlist/lesson.md new file mode 100644 index 00000000..0e29c2db --- /dev/null +++ b/langs/tr/tutorials/bindings_classlist/lesson.md @@ -0,0 +1,27 @@ +Solid uses `class` to set the `className` property on an element. However it is often convenient to conditionally set classes. For that reason, Solid has a built-in `classList` JSX attribute that takes an object where the key is the class name(s) and the value is a boolean expression. When true, the class is applied, and when false, it is removed. + +In the example, we can replace: + +```jsx + +``` + +with: + +```jsx + +``` + +Remember that you can apply names dynamically like what you'd receive in CSS modules as well: + +```jsx +import { active } from "./style.module.css" + +
    +``` diff --git a/langs/tr/tutorials/bindings_classlist/solved.json b/langs/tr/tutorials/bindings_classlist/solved.json new file mode 100644 index 00000000..666cf63c --- /dev/null +++ b/langs/tr/tutorials/bindings_classlist/solved.json @@ -0,0 +1,13 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nimport \"./style.css\";\n\nfunction App() {\n const [current, setCurrent] = createSignal(\"foo\");\n\n return <>\n setCurrent('foo')}\n >foo\n setCurrent('bar')}\n >bar\n setCurrent('baz')}\n >baz\n ;\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "style", + "type": "css", + "content": "button {\n display: block;\n}\n\n.selected {\n background-color: #ff3e00;\n color: white;\n}" + } + ] +} diff --git a/langs/tr/tutorials/bindings_directives/lesson.json b/langs/tr/tutorials/bindings_directives/lesson.json new file mode 100644 index 00000000..26f8a117 --- /dev/null +++ b/langs/tr/tutorials/bindings_directives/lesson.json @@ -0,0 +1,17 @@ +{ + "files": [ + { + "name": "main", + "content": "// @ts-nocheck\nimport { render } from \"solid-js/web\";\nimport { createSignal, Show } from \"solid-js\";\nimport clickOutside from \"./click-outside\";\nimport \"./style.css\";\n\nfunction App() {\n const [show, setShow] = createSignal(false);\n\n return (\n setShow(true)}>Open Modal}\n >\n
    \n Some Modal\n
    \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "click-outside", + "content": "import { onCleanup } from \"solid-js\";\n\nexport default function clickOutside(el, accessor) {\n // implement here\n}\n" + }, + { + "name": "style", + "type": "css", + "content": ".modal {\n padding: 16px;\n border: 1px solid #444;\n box-shadow: 4px 4px #88888866;\n}" + } + ] +} \ No newline at end of file diff --git a/langs/tr/tutorials/bindings_directives/lesson.md b/langs/tr/tutorials/bindings_directives/lesson.md new file mode 100644 index 00000000..5b144d3a --- /dev/null +++ b/langs/tr/tutorials/bindings_directives/lesson.md @@ -0,0 +1,26 @@ +Solid supports custom directives through the `use:` namespace. This is just a syntactic sugar over `ref`, but is useful in that it resembles typical bindings and there can be multiple bindings on the same element without conflict. This makes it a better tool for reusable DOM element behavior. + +A custom directive is a function taking arguments `(element, valueAccesor)`, where `element` is the DOM element with the `use:` attribute, and `valueAccessor` is a getter function for the value assigned to the attribute. As long as the function is imported in scope, you can use it with `use:`. + +> Important: `use:` is detected by the compiler to be transformed, and the function is required to be in scope, so it cannot be part of spreads or applied to a component. + +In the example, we are going to make a wrapper for basic click-outside behavior to close a popup or modal. First we need to import and use our `clickOutside` directive on our element: + +```jsx + +``` + +Open `click-outside.tsx`, where we will be defining our custom directive. This directive defines a click handler that we bind to the body and cleanup when it is time: + +```jsx +export default function clickOutside(el, accessor) { + const onClick = (e) => !el.contains(e.target) && accessor()?.(); + document.body.addEventListener("click", onClick); + + onCleanup(() => document.body.removeEventListener("click", onClick)); +} +``` + +Now you should be able to go back and forth between opening and closing the modal. diff --git a/langs/tr/tutorials/bindings_directives/solved.json b/langs/tr/tutorials/bindings_directives/solved.json new file mode 100644 index 00000000..84830904 --- /dev/null +++ b/langs/tr/tutorials/bindings_directives/solved.json @@ -0,0 +1,17 @@ +{ + "files": [ + { + "name": "main", + "content": "// @ts-nocheck\nimport { render } from \"solid-js/web\";\nimport { createSignal, Show } from \"solid-js\";\nimport clickOutside from \"./click-outside\";\nimport \"./style.css\";\n\nfunction App() {\n const [show, setShow] = createSignal(false);\n\n return (\n setShow(true)}>Open Modal}\n >\n
    setShow(false)}>\n Some Modal\n
    \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "click-outside", + "content": "import { onCleanup } from \"solid-js\";\n\nexport default function clickOutside(el, accessor) {\n const onClick = (e) => !el.contains(e.target) && accessor()?.();\n document.body.addEventListener(\"click\", onClick);\n\n onCleanup(() => document.body.removeEventListener(\"click\", onClick));\n}\n" + }, + { + "name": "style", + "type": "css", + "content": ".modal {\n padding: 16px;\n border: 1px solid #444;\n box-shadow: 4px 4px #88888866;\n}" + } + ] +} diff --git a/langs/tr/tutorials/bindings_events/lesson.json b/langs/tr/tutorials/bindings_events/lesson.json new file mode 100644 index 00000000..0c31e073 --- /dev/null +++ b/langs/tr/tutorials/bindings_events/lesson.json @@ -0,0 +1,13 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nimport \"./style.css\";\n\nfunction App() {\n const [pos, setPos] = createSignal({x: 0, y: 0});\n\n function handleMouseMove(event) {\n setPos({\n x: event.clientX,\n y: event.clientY\n });\n }\n\n return (\n
    \n The mouse position is {pos().x} x {pos().y}\n
    \n );\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "style", + "type": "css", + "content": "div { width: 100%; height: 100%; }" + } + ] +} diff --git a/langs/tr/tutorials/bindings_events/lesson.md b/langs/tr/tutorials/bindings_events/lesson.md new file mode 100644 index 00000000..9fea8f2b --- /dev/null +++ b/langs/tr/tutorials/bindings_events/lesson.md @@ -0,0 +1,22 @@ +Events in Solid are attributes prefixed with `on`. They are treated specially in a few ways. First, they do not follow the normal heuristics for wrapping. In many cases, it is difficult to determine the difference between a Signal and an event handler. And so, since events are called and don't require reactivity to update, they are only bound initially. You can always just have your handler run different code based on the current state of your app. + +Common UI events (that bubble and are composed) are automatically delegated to the document. To improve delegated performance, Solid supports an array syntax to call the handler with data (as the first argument) without creating additional closures: + +```jsx +const handler = (data, event) => /*...*/ + + +``` + +In the example, let's attach the handler to the `mousemove` event: +```jsx +
    + The mouse position is {pos().x} x {pos().y} +
    +``` + +All `on` bindings are case insensitive which means that event names need to be in lowercase. For example, `onMouseMove` monitors the event name `mousemove`. If you need to support other casings or not use event delegation, you can use `on:` namespace to match event handlers that follows the colon: + +```jsx + +``` diff --git a/langs/tr/tutorials/bindings_events/solved.json b/langs/tr/tutorials/bindings_events/solved.json new file mode 100644 index 00000000..913e7869 --- /dev/null +++ b/langs/tr/tutorials/bindings_events/solved.json @@ -0,0 +1,13 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nimport \"./style.css\";\n\nfunction App() {\n const [pos, setPos] = createSignal({x: 0, y: 0});\n\n function handleMouseMove(event) {\n setPos({\n x: event.clientX,\n y: event.clientY\n });\n }\n\n return (\n
    \n The mouse position is {pos().x} x {pos().y}\n
    \n );\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "style", + "type": "css", + "content": "div { width: 100%; height: 100%; }" + } + ] +} diff --git a/langs/tr/tutorials/bindings_forward_refs/lesson.json b/langs/tr/tutorials/bindings_forward_refs/lesson.json new file mode 100644 index 00000000..ab19dd11 --- /dev/null +++ b/langs/tr/tutorials/bindings_forward_refs/lesson.json @@ -0,0 +1,17 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { onMount, onCleanup } from \"solid-js\";\n\nimport Canvas from \"./canvas\";\n\nfunction App() {\n let canvas;\n onMount(() => {\n const ctx = canvas.getContext(\"2d\");\n let frame = requestAnimationFrame(loop);\n\n function loop(t) {\n frame = requestAnimationFrame(loop);\n\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n\n for (let p = 0; p < imageData.data.length; p += 4) {\n const i = p / 4;\n const x = i % canvas.width;\n const y = (i / canvas.height) >>> 0;\n\n const r = 64 + (128 * x) / canvas.width + 64 * Math.sin(t / 1000);\n const g = 64 + (128 * y) / canvas.height + 64 * Math.cos(t / 1000);\n const b = 128;\n\n imageData.data[p + 0] = r;\n imageData.data[p + 1] = g;\n imageData.data[p + 2] = b;\n imageData.data[p + 3] = 255;\n }\n\n ctx.putImageData(imageData, 0, 0);\n }\n\n onCleanup(() => cancelAnimationFrame(frame));\n });\n\n return ;\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "canvas", + "content": "import \"./style.css\";\n\nexport default function Canvas(props) {\n return ;\n}\n" + }, + { + "name": "style", + "type": "css", + "content": "canvas {\n background-color: #666;\n -webkit-mask: url(https://www.solidjs.com/img/logo/dark-without-wordmark/logo.svg) 50% 50% no-repeat;\n mask: url(https://www.solidjs.com/img/logo/dark-without-wordmark/logo.svg) 50% 50% no-repeat;\n}" + } + ] +} diff --git a/langs/tr/tutorials/bindings_forward_refs/lesson.md b/langs/tr/tutorials/bindings_forward_refs/lesson.md new file mode 100644 index 00000000..95a3a203 --- /dev/null +++ b/langs/tr/tutorials/bindings_forward_refs/lesson.md @@ -0,0 +1,9 @@ +On many occassions, you might want to expose a ref from inside a component to a parent. The way we do this is still by using the `ref` attribute. From the outside, using `ref` on a component works very similar to using `ref` on a native element. You can pass it a variable to be assigned or a callback function. + +However, it is the component author's responsibility to connect that `ref` to an internal element to forward it back up. To do so, we leverage `props.ref`. This is a callback form of `ref` if either type of `ref` is given, but this detail is mostly hidden from you as you will more than likely just be assigning it directly to the `ref` attribute of one of the elements or components in this component's JSX. + +To get the logo animating again, we need to forward the ref from `canvas.tsx`: + +```jsx + +``` diff --git a/langs/tr/tutorials/bindings_forward_refs/solved.json b/langs/tr/tutorials/bindings_forward_refs/solved.json new file mode 100644 index 00000000..40c53fe8 --- /dev/null +++ b/langs/tr/tutorials/bindings_forward_refs/solved.json @@ -0,0 +1,17 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { onMount, onCleanup } from \"solid-js\";\n\nimport Canvas from \"./canvas\";\n\nfunction App() {\n let canvas;\n onMount(() => {\n const ctx = canvas.getContext(\"2d\");\n let frame = requestAnimationFrame(loop);\n\n function loop(t) {\n frame = requestAnimationFrame(loop);\n\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n\n for (let p = 0; p < imageData.data.length; p += 4) {\n const i = p / 4;\n const x = i % canvas.width;\n const y = (i / canvas.height) >>> 0;\n\n const r = 64 + (128 * x) / canvas.width + 64 * Math.sin(t / 1000);\n const g = 64 + (128 * y) / canvas.height + 64 * Math.cos(t / 1000);\n const b = 128;\n\n imageData.data[p + 0] = r;\n imageData.data[p + 1] = g;\n imageData.data[p + 2] = b;\n imageData.data[p + 3] = 255;\n }\n\n ctx.putImageData(imageData, 0, 0);\n }\n\n onCleanup(() => cancelAnimationFrame(frame));\n });\n\n return ;\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "canvas", + "content": "import \"./style.css\";\n\nexport default function Canvas(props) {\n return ;\n}\n" + }, + { + "name": "style", + "type": "css", + "content": "canvas {\n background-color: #666;\n -webkit-mask: url(https://www.solidjs.com/img/logo/dark-without-wordmark/logo.svg) 50% 50% no-repeat;\n mask: url(https://www.solidjs.com/img/logo/dark-without-wordmark/logo.svg) 50% 50% no-repeat;\n}" + } + ] +} \ No newline at end of file diff --git a/langs/tr/tutorials/bindings_refs/lesson.json b/langs/tr/tutorials/bindings_refs/lesson.json new file mode 100644 index 00000000..efb164bd --- /dev/null +++ b/langs/tr/tutorials/bindings_refs/lesson.json @@ -0,0 +1,13 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { onMount, onCleanup } from \"solid-js\";\n\nimport \"./style.css\";\n\nfunction App() {\n let canvas;\n onMount(() => {\n const ctx = canvas.getContext(\"2d\");\n let frame = requestAnimationFrame(loop);\n\n function loop(t) {\n frame = requestAnimationFrame(loop);\n\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n\n for (let p = 0; p < imageData.data.length; p += 4) {\n const i = p / 4;\n const x = i % canvas.width;\n const y = (i / canvas.height) >>> 0;\n\n const r = 64 + (128 * x) / canvas.width + 64 * Math.sin(t / 1000);\n const g = 64 + (128 * y) / canvas.height + 64 * Math.cos(t / 1000);\n const b = 128;\n\n imageData.data[p + 0] = r;\n imageData.data[p + 1] = g;\n imageData.data[p + 2] = b;\n imageData.data[p + 3] = 255;\n }\n\n ctx.putImageData(imageData, 0, 0);\n }\n\n onCleanup(() => cancelAnimationFrame(frame));\n });\n\n return ;\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "style", + "type": "css", + "content": "canvas {\n background-color: #666;\n -webkit-mask: url(https://www.solidjs.com/img/logo/dark-without-wordmark/logo.svg) 50% 50% no-repeat;\n mask: url(https://www.solidjs.com/img/logo/dark-without-wordmark/logo.svg) 50% 50% no-repeat;\n}" + } + ] +} diff --git a/langs/tr/tutorials/bindings_refs/lesson.md b/langs/tr/tutorials/bindings_refs/lesson.md new file mode 100644 index 00000000..0b6cac01 --- /dev/null +++ b/langs/tr/tutorials/bindings_refs/lesson.md @@ -0,0 +1,27 @@ +You can always get a reference to a DOM element in Solid through assignment, since JSX creates actual DOM elements. For example: + +```jsx +const myDiv =
    My Element
    ; +``` + +However, there is benefit to not breaking your elements out and instead putting them in a single contiguous JSX template, as it allows Solid to better optimize their creation. + +Instead you can get a reference to an element in Solid using the `ref` attribute. Refs are basically assignments like the example above, which happen at creation time before they are attached to the document DOM. Just declare a variable, pass it in as a `ref` attribute, and the variable will be assigned to: + +```jsx +let myDiv; + +
    My Element
    +``` + +So let's get a reference to our canvas element and animate it: + +```jsx + +``` + +Refs can also take the form of a callback function. This can be convenient for encapsulating logic, especially when you don't need to wait until the elements are attached. For example: + +```jsx +
    /* do something with el... */}>My Element
    +``` diff --git a/langs/tr/tutorials/bindings_refs/solved.json b/langs/tr/tutorials/bindings_refs/solved.json new file mode 100644 index 00000000..bb56ea03 --- /dev/null +++ b/langs/tr/tutorials/bindings_refs/solved.json @@ -0,0 +1,13 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { onMount, onCleanup } from \"solid-js\";\n\nimport \"./style.css\";\n\nfunction App() {\n let canvas;\n onMount(() => {\n const ctx = canvas.getContext(\"2d\");\n let frame = requestAnimationFrame(loop);\n\n function loop(t) {\n frame = requestAnimationFrame(loop);\n\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n\n for (let p = 0; p < imageData.data.length; p += 4) {\n const i = p / 4;\n const x = i % canvas.width;\n const y = (i / canvas.height) >>> 0;\n\n const r = 64 + (128 * x) / canvas.width + 64 * Math.sin(t / 1000);\n const g = 64 + (128 * y) / canvas.height + 64 * Math.cos(t / 1000);\n const b = 128;\n\n imageData.data[p + 0] = r;\n imageData.data[p + 1] = g;\n imageData.data[p + 2] = b;\n imageData.data[p + 3] = 255;\n }\n\n ctx.putImageData(imageData, 0, 0);\n }\n\n onCleanup(() => cancelAnimationFrame(frame));\n });\n\n return ;\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "style", + "type": "css", + "content": "canvas {\n background-color: #666;\n -webkit-mask: url(https://www.solidjs.com/img/logo/dark-without-wordmark/logo.svg) 50% 50% no-repeat;\n mask: url(https://www.solidjs.com/img/logo/dark-without-wordmark/logo.svg) 50% 50% no-repeat;\n}" + } + ] +} diff --git a/langs/tr/tutorials/bindings_spreads/lesson.json b/langs/tr/tutorials/bindings_spreads/lesson.json new file mode 100644 index 00000000..c89e7f1a --- /dev/null +++ b/langs/tr/tutorials/bindings_spreads/lesson.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport Info from \"./info\";\n\nconst pkg = {\n name: \"solid-js\",\n version: 1,\n speed: \"⚡️\",\n website: \"https://solidjs.com\",\n};\n\nfunction App() {\n return (\n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "info", + "content": "export default function Info(props) {\n return (\n

    \n The {props.name} package is {props.speed} fast. Download\n version {props.version} from{\" \"}\n npm and{\" \"}\n learn more here\n

    \n );\n}\n" + } + ] +} diff --git a/langs/tr/tutorials/bindings_spreads/lesson.md b/langs/tr/tutorials/bindings_spreads/lesson.md new file mode 100644 index 00000000..aa6c72c6 --- /dev/null +++ b/langs/tr/tutorials/bindings_spreads/lesson.md @@ -0,0 +1,9 @@ +Sometimes your components and elements accept a variable number of attributes and it makes sense to pass them down as an object instead of individually. This is especially true when wrapping a DOM element in a component, a common practice when making design systems. + +For this we use the spread operator `...`. + +We can pass an object with a variable number of properties: + +```jsx + +``` diff --git a/langs/tr/tutorials/bindings_spreads/solved.json b/langs/tr/tutorials/bindings_spreads/solved.json new file mode 100644 index 00000000..fd12259f --- /dev/null +++ b/langs/tr/tutorials/bindings_spreads/solved.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport Info from \"./info\";\n\nconst pkg = {\n name: \"solid-js\",\n version: 1,\n speed: \"⚡️\",\n website: \"https://solidjs.com\",\n};\n\nfunction App() {\n return ;\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "info", + "content": "export default function Info(props) {\n return (\n

    \n The {props.name} package is {props.speed} fast. Download\n version {props.version} from{\" \"}\n npm and{\" \"}\n learn more here\n

    \n );\n}\n" + } + ] +} diff --git a/langs/tr/tutorials/bindings_style/lesson.json b/langs/tr/tutorials/bindings_style/lesson.json new file mode 100644 index 00000000..11f8610e --- /dev/null +++ b/langs/tr/tutorials/bindings_style/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nfunction App() {\n const [num, setNum] = createSignal(0);\n setInterval(() => setNum((num() + 1) % 255), 30)\n\n return
    Some Text
    ;\n}\n\nrender(() => , document.getElementById('app'));" + } + ] +} diff --git a/langs/tr/tutorials/bindings_style/lesson.md b/langs/tr/tutorials/bindings_style/lesson.md new file mode 100644 index 00000000..669a7eee --- /dev/null +++ b/langs/tr/tutorials/bindings_style/lesson.md @@ -0,0 +1,20 @@ +The `style` attribute in Solid accepts either style strings or objects. +However the object form differs from `Element.prototype.style` and instead is a wrapper for calling `style.setProperty`. This means that keys take the dash-case form, like "background-color" rather than "backgroundColor", and that any units must be explicitly provided (e.g., `width: 500px` rather than `width: 500`). + + +This also means that we have the ability to set CSS variables: + +```js +
    +``` + +Let's animate our div with a few inline styles: +```jsx +
    + Some Text +
    +``` \ No newline at end of file diff --git a/langs/tr/tutorials/bindings_style/solved.json b/langs/tr/tutorials/bindings_style/solved.json new file mode 100644 index 00000000..5915cfbf --- /dev/null +++ b/langs/tr/tutorials/bindings_style/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nfunction App() {\n const [num, setNum] = createSignal(0);\n setInterval(() => setNum((num() + 1) % 255), 30)\n\n return (\n
    \n Some Text\n
    \n );\n}\n\nrender(() => , document.getElementById('app'));" + } + ] +} diff --git a/langs/tr/tutorials/directory.json b/langs/tr/tutorials/directory.json new file mode 100644 index 00000000..ede4aeaf --- /dev/null +++ b/langs/tr/tutorials/directory.json @@ -0,0 +1,162 @@ +[ + { + "lessonName": "Introduction/Basics", + "internalName": "introduction_basics" + }, + { + "lessonName": "Introduction/JSX", + "internalName": "introduction_jsx" + }, + { + "lessonName": "Introduction/Components", + "internalName": "introduction_components" + }, + { + "lessonName": "Introduction/Signals", + "internalName": "introduction_signals" + }, + { + "lessonName": "Introduction/Effects", + "internalName": "introduction_effects" + }, + { + "lessonName": "Introduction/Derived Signals", + "internalName": "introduction_derived" + }, + { + "lessonName": "Introduction/Memos", + "internalName": "introduction_memos" + }, + { + "lessonName": "Control Flow/Show", + "internalName": "flow_show" + }, + { + "lessonName": "Control Flow/For", + "internalName": "flow_for" + }, + { + "lessonName": "Control Flow/Index", + "internalName": "flow_index" + }, + { + "lessonName": "Control Flow/Switch", + "internalName": "flow_switch" + }, + { + "lessonName": "Control Flow/Dynamic", + "internalName": "flow_dynamic" + }, + { + "lessonName": "Control Flow/Portal", + "internalName": "flow_portal" + }, + { + "lessonName": "Control Flow/Error Boundary", + "internalName": "flow_error_boundary" + }, + { + "lessonName": "Lifecycles/onMount", + "internalName": "lifecycles_onmount" + }, + { + "lessonName": "Lifecycles/onCleanup", + "internalName": "lifecycles_oncleanup" + }, + { + "lessonName": "Bindings/Events", + "internalName": "bindings_events" + }, + { + "lessonName": "Bindings/Style", + "internalName": "bindings_style" + }, + { + "lessonName": "Bindings/ClassList", + "internalName": "bindings_classlist" + }, + { + "lessonName": "Bindings/Refs", + "internalName": "bindings_refs" + }, + { + "lessonName": "Bindings/Forwarding Refs", + "internalName": "bindings_forward_refs" + }, + { + "lessonName": "Bindings/Spreads", + "internalName": "bindings_spreads" + }, + { + "lessonName": "Bindings/Directives", + "internalName": "bindings_directives" + }, + { + "lessonName": "Props/Default Props", + "internalName": "props_defaults" + }, + { + "lessonName": "Props/Splitting Props", + "internalName": "props_split" + }, + { + "lessonName": "Props/Children", + "internalName": "props_children" + }, + { + "lessonName": "Stores/Nested Reactivity", + "internalName": "stores_nested_reactivity" + }, + { + "lessonName": "Stores/Create Store", + "internalName": "stores_createstore" + }, + { + "lessonName": "Stores/Mutation", + "internalName": "stores_mutation" + }, + { + "lessonName": "Stores/Context", + "internalName": "stores_context" + }, + { + "lessonName": "Stores/Immutable Stores", + "internalName": "stores_immutable" + }, + { + "lessonName": "Stores/Without Context", + "internalName": "stores_nocontext" + }, + { + "lessonName": "Reactivity/Batching Updates", + "internalName": "reactivity_batch" + }, + { + "lessonName": "Reactivity/Untrack", + "internalName": "reactivity_untrack" + }, + { + "lessonName": "Reactivity/On", + "internalName": "reactivity_on" + }, + { + "lessonName": "Async/Lazy Components", + "internalName": "async_lazy" + }, + { + "lessonName": "Async/Resources", + "internalName": "async_resources" + }, + { + "lessonName": "Async/Suspense", + "internalName": "async_suspense" + }, + { + "lessonName": "Async/Suspense List", + "internalName": "async_suspense_list" + }, + { + "lessonName": "Async/Transitions", + "internalName": "async_transitions" + } +] diff --git a/langs/tr/tutorials/flow_dynamic/lesson.json b/langs/tr/tutorials/flow_dynamic/lesson.json new file mode 100644 index 00000000..4d9a171d --- /dev/null +++ b/langs/tr/tutorials/flow_dynamic/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render, Dynamic } from \"solid-js/web\";\nimport { createSignal, Switch, Match, For } from \"solid-js\";\n\nconst RedThing = () => Red Thing;\nconst GreenThing = () => Green Thing;\nconst BlueThing = () => Blue Thing;\n\nconst options = {\n red: RedThing,\n green: GreenThing,\n blue: BlueThing\n}\n\nfunction App() {\n const [selected, setSelected] = createSignal(\"red\");\n\n return (\n <>\n \n }>\n \n \n \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/flow_dynamic/lesson.md b/langs/tr/tutorials/flow_dynamic/lesson.md new file mode 100644 index 00000000..7a09c912 --- /dev/null +++ b/langs/tr/tutorials/flow_dynamic/lesson.md @@ -0,0 +1,18 @@ +The `` tag is useful when you render from data. It lets you pass either a string for a native element or a component function and it will render that with the rest of the provided props. + +This is often more compact than writing a number of `` or `` components. + +In the example, we can replace the `` statement: + +```jsx +}> + + + +``` + +with: + +```jsx + +``` diff --git a/langs/tr/tutorials/flow_dynamic/solved.json b/langs/tr/tutorials/flow_dynamic/solved.json new file mode 100644 index 00000000..b8a845b8 --- /dev/null +++ b/langs/tr/tutorials/flow_dynamic/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render, Dynamic } from \"solid-js/web\";\nimport { createSignal, For } from \"solid-js\";\n\nconst RedThing = () => Red Thing;\nconst GreenThing = () => Green Thing;\nconst BlueThing = () => Blue Thing;\n\nconst options = {\n red: RedThing,\n green: GreenThing,\n blue: BlueThing\n}\n\nfunction App() {\n const [selected, setSelected] = createSignal(\"red\");\n\n return (\n <>\n \n \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/flow_error_boundary/lesson.json b/langs/tr/tutorials/flow_error_boundary/lesson.json new file mode 100644 index 00000000..be53fdac --- /dev/null +++ b/langs/tr/tutorials/flow_error_boundary/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { ErrorBoundary } from \"solid-js\";\n\nconst Broken = (props) => {\n throw new Error(\"Oh No\");\n return <>Never Getting Here\n}\n\nfunction App() {\n return (\n <>\n
    Before
    \n \n
    After
    \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/flow_error_boundary/lesson.md b/langs/tr/tutorials/flow_error_boundary/lesson.md new file mode 100644 index 00000000..60279577 --- /dev/null +++ b/langs/tr/tutorials/flow_error_boundary/lesson.md @@ -0,0 +1,9 @@ +A JavaScript error originating in the UI shouldn’t break the whole app. Error boundaries are components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. + +A component has crashed our example. Let's wrap it in an Error Boundary that displays the error. + +```jsx + err}> + + +``` diff --git a/langs/tr/tutorials/flow_error_boundary/solved.json b/langs/tr/tutorials/flow_error_boundary/solved.json new file mode 100644 index 00000000..25ed4b57 --- /dev/null +++ b/langs/tr/tutorials/flow_error_boundary/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { ErrorBoundary } from \"solid-js\";\n\nconst Broken = (props) => {\n throw new Error(\"Oh No\");\n return <>Never Getting Here\n}\n\nfunction App() {\n return (\n <>\n
    Before
    \n err}>\n \n \n
    After
    \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/flow_for/lesson.json b/langs/tr/tutorials/flow_for/lesson.json new file mode 100644 index 00000000..4b1b4150 --- /dev/null +++ b/langs/tr/tutorials/flow_for/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\nimport { createSignal, For } from 'solid-js';\n\nfunction App() {\n const [cats, setCats] = createSignal([\n { id: 'J---aiyznGQ', name: 'Keyboard Cat' },\n { id: 'z_AbfPXTKms', name: 'Maru' },\n { id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }\n ]);\n \n return (\n \n );\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} diff --git a/langs/tr/tutorials/flow_for/lesson.md b/langs/tr/tutorials/flow_for/lesson.md new file mode 100644 index 00000000..b930b0ea --- /dev/null +++ b/langs/tr/tutorials/flow_for/lesson.md @@ -0,0 +1,19 @@ +The `` component is the best way to loop over an array of objects. As the array changes, `` updates or moves items in the DOM rather than recreating them. Let's look at an example. + +```jsx +{(cat, i) => +
  • + + {i() + 1}: {cat.name} + +
  • +}
    +``` + +There is one prop on the `` component: `each`, where you pass the array to loop over. + +Then, instead of writing nodes directly between `` and ``, you pass a _callback_. This is a function similar to JavaScript's [`map` callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#parameters). For each element in the array, the callback is called with the element as the first argument and the index as the second. (`cat` and `i` in this example.) You can then make use of those in the callback, which should return a node to be rendered. + +Note that the index is a _signal_, not a constant number. This is because `` is "keyed by reference": each node that it renders is coupled to an element in the array. In other words, if an element changes placement in the array, rather than being destroyed and recreated, the corresponding node will move too and its index will change. + +The `each` prop expects an array, but you can turn other iterable objects into arrays with utilities like [`Array.from`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from), [`Object.keys`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys), or [`spread syntax`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax). diff --git a/langs/tr/tutorials/flow_for/solved.json b/langs/tr/tutorials/flow_for/solved.json new file mode 100644 index 00000000..b2b2d8ba --- /dev/null +++ b/langs/tr/tutorials/flow_for/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\nimport { createSignal, For } from 'solid-js';\n\nfunction App() {\n const [cats, setCats] = createSignal([\n { id: 'J---aiyznGQ', name: 'Keyboard Cat' },\n { id: 'z_AbfPXTKms', name: 'Maru' },\n { id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }\n ]);\n \n return (\n \n );\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} diff --git a/langs/tr/tutorials/flow_index/lesson.json b/langs/tr/tutorials/flow_index/lesson.json new file mode 100644 index 00000000..dfffada6 --- /dev/null +++ b/langs/tr/tutorials/flow_index/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\nimport { createSignal, Index } from 'solid-js';\n\nfunction App() {\n const [cats, setCats] = createSignal([\n { id: 'J---aiyznGQ', name: 'Keyboard Cat' },\n { id: 'z_AbfPXTKms', name: 'Maru' },\n { id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }\n ]);\n \n return (\n \n );\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} diff --git a/langs/tr/tutorials/flow_index/lesson.md b/langs/tr/tutorials/flow_index/lesson.md new file mode 100644 index 00000000..5c00894f --- /dev/null +++ b/langs/tr/tutorials/flow_index/lesson.md @@ -0,0 +1,21 @@ +You now know how to render lists in Solid with ``, but Solid also provides the `` component, which will cause less rerenders in certain situations. + +When the array updates, the `` component uses referential equality to compare elements to the last state of the array. But this isn't always desired. + +In JavaScript, primitives (like strings and numbers) are always compared by value. When using `` with primitive values or arrays of arrays, we could cause a lot of unnecessary rendering. If we used `` to map a list of strings to `` fields that could edit each, every change to that value would cause the `` to be recreated. + +The `` component is provided for these cases. As a rule of thumb, when working with primitives use ``. + +```jsx +{(cat, i) => +
  • + + {i + 1}: {cat().name} + +
  • +}
    +``` + + It has a similar signature to ``, except this time the item is the signal and the index is fixed. Each rendered node corresponds to a spot in the array. Whenever the data in that spot changes, the signal will update. + +`` cares about each piece of data in your array, and the position of that data can change; `` cares about each index in your array, and the content at each index can change. diff --git a/langs/tr/tutorials/flow_index/solved.json b/langs/tr/tutorials/flow_index/solved.json new file mode 100644 index 00000000..0fb0f59e --- /dev/null +++ b/langs/tr/tutorials/flow_index/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\nimport { createSignal, Index } from 'solid-js';\n\nfunction App() {\n const [cats, setCats] = createSignal([\n { id: 'J---aiyznGQ', name: 'Keyboard Cat' },\n { id: 'z_AbfPXTKms', name: 'Maru' },\n { id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }\n ]);\n \n return (\n \n );\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} diff --git a/langs/tr/tutorials/flow_portal/lesson.json b/langs/tr/tutorials/flow_portal/lesson.json new file mode 100644 index 00000000..024fe7fa --- /dev/null +++ b/langs/tr/tutorials/flow_portal/lesson.json @@ -0,0 +1,13 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render, Portal } from \"solid-js/web\";\nimport \"./styles.css\";\n\nfunction App() {\n return (\n
    \n

    Just some text inside a div that has a restricted size.

    \n
    \n

    Popup

    \n

    Some text you might need for something or other.

    \n
    \n
    \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "styles", + "type": "css", + "content": ".app-container {\n width: 200px;\n height: 100px;\n overflow: hidden;\n}\n\n.popup {\n position: relative;\n z-index: 2;\n background: #ddd;\n padding: 1rem;\n min-height: 200px;\n min-width: 200px;\n}\n\n.popup::after {\n content: \" \";\n position: absolute;\n bottom: 100%;\n left: 50%;\n margin-left: -5px;\n border-width: 5px;\n border-style: solid;\n border-color: transparent transparent #ddd transparent;\n}" + } + ] +} diff --git a/langs/tr/tutorials/flow_portal/lesson.md b/langs/tr/tutorials/flow_portal/lesson.md new file mode 100644 index 00000000..81b99ecf --- /dev/null +++ b/langs/tr/tutorials/flow_portal/lesson.md @@ -0,0 +1,14 @@ +Sometimes it's beneficial to insert elements outside the normal flow of the app. Z-indexes are sometimes insufficient to deal with render contexts for floating elements like Modals. + +Solid has a `` component whose child content will be inserted at the location of your choosing. By default, its elements will be rendered in a `
    ` in the `document.body`. + +In the example, we see our information popup get cut off. We can solve this by pulling it out of the flow by wrapping the element in a ``: + +```jsx + + + +``` diff --git a/langs/tr/tutorials/flow_portal/solved.json b/langs/tr/tutorials/flow_portal/solved.json new file mode 100644 index 00000000..2de9f10b --- /dev/null +++ b/langs/tr/tutorials/flow_portal/solved.json @@ -0,0 +1,13 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render, Portal } from \"solid-js/web\";\nimport \"./styles.css\";\n\nfunction App() {\n return (\n
    \n

    Just some text inside a div that has a restricted size.

    \n \n
    \n

    Popup

    \n

    Some text you might need for something or other.

    \n
    \n
    \n
    \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "styles", + "type": "css", + "content": ".app-container {\n width: 200px;\n height: 100px;\n overflow: hidden;\n}\n\n.popup {\n position: relative;\n z-index: 2;\n background: #ddd;\n padding: 1rem;\n min-height: 200px;\n min-width: 200px;\n}\n\n.popup::after {\n content: \" \";\n position: absolute;\n bottom: 100%;\n left: 50%;\n margin-left: -5px;\n border-width: 5px;\n border-style: solid;\n border-color: transparent transparent #ddd transparent;\n}" + } + ] +} diff --git a/langs/tr/tutorials/flow_show/lesson.json b/langs/tr/tutorials/flow_show/lesson.json new file mode 100644 index 00000000..53afe6f3 --- /dev/null +++ b/langs/tr/tutorials/flow_show/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\nimport { createSignal, Show } from 'solid-js';\n\nfunction App() {\n const [loggedIn, setLoggedIn] = createSignal(false);\n const toggle = () => setLoggedIn(!loggedIn())\n \n return (\n <>\n \n \n \n );\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} diff --git a/langs/tr/tutorials/flow_show/lesson.md b/langs/tr/tutorials/flow_show/lesson.md new file mode 100644 index 00000000..4ee51a95 --- /dev/null +++ b/langs/tr/tutorials/flow_show/lesson.md @@ -0,0 +1,16 @@ +JSX allows you to use JavaScript to control the logic flow in the templates. However, without a Virtual DOM, naive use of things like `Array.prototype.map` would wastefully recreate all the DOM nodes on every update. Instead it is common for Reactive libraries to use template helpers. In Solid we wrap them in components. + +The most basic control flow is the conditional. Solid's compiler is smart enough to optimally handle ternaries (`a ? b : c`) and boolean expressions (`a && b`). However, often it is more readable to use Solid's `` component. + +In the example, we would like to show only the appropriate button that reflects the current state (whether the user is logged in). Update the JSX to: +```jsx +Log in} +> + + +``` +The `fallback` prop acts as the `else` and will show when the condition passed to `when` is not truthy. + +Now clicking the button will change back and forth like you would expect. diff --git a/langs/tr/tutorials/flow_show/solved.json b/langs/tr/tutorials/flow_show/solved.json new file mode 100644 index 00000000..9f8ffe63 --- /dev/null +++ b/langs/tr/tutorials/flow_show/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\nimport { createSignal, Show } from 'solid-js';\n\nfunction App() {\n const [loggedIn, setLoggedIn] = createSignal(false);\n const toggle = () => setLoggedIn(!loggedIn())\n \n return (\n Log in}\n >\n \n \n );\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} diff --git a/langs/tr/tutorials/flow_switch/lesson.json b/langs/tr/tutorials/flow_switch/lesson.json new file mode 100644 index 00000000..7ae3bc59 --- /dev/null +++ b/langs/tr/tutorials/flow_switch/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, Show, Switch, Match } from \"solid-js\";\n\nfunction App() {\n const [x] = createSignal(7);\n\n return (\n 10}\n fallback={\n x()}\n fallback={

    {x()} is between 5 and 10

    }\n >\n

    {x()} is less than 5

    \n \n }\n >\n

    {x()} is greater than 10

    \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/flow_switch/lesson.md b/langs/tr/tutorials/flow_switch/lesson.md new file mode 100644 index 00000000..f460fd82 --- /dev/null +++ b/langs/tr/tutorials/flow_switch/lesson.md @@ -0,0 +1,16 @@ +Sometimes you need to deal with conditionals with more than 2 mutual exclusive outcomes. For this case, we have the `` and `` components modeled roughly after JavaScript's `switch`/`case`. + +It will try in order to match each condition, stopping to render the first that evaluates to true. Failing all of them, it will render the the fallback. + +In the example, we can replace our nested `` components with this: + +```jsx +{x()} is between 5 and 10

    }> + 10}> +

    {x()} is greater than 10

    +
    + x()}> +

    {x()} is less than 5

    +
    +
    +``` diff --git a/langs/tr/tutorials/flow_switch/solved.json b/langs/tr/tutorials/flow_switch/solved.json new file mode 100644 index 00000000..0900e88c --- /dev/null +++ b/langs/tr/tutorials/flow_switch/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, Switch, Match } from \"solid-js\";\n\nfunction App() {\n const [x] = createSignal(7);\n\n return (\n {x()} is between 5 and 10

    }>\n 10} >\n

    {x()} is greater than 10

    \n
    \n x()}>\n

    {x()} is less than 5

    \n
    \n
    \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/introduction_basics/lesson.json b/langs/tr/tutorials/introduction_basics/lesson.json new file mode 100644 index 00000000..0d9dc883 --- /dev/null +++ b/langs/tr/tutorials/introduction_basics/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\n\nfunction HelloWorld() {\n return
    Hello World!
    ;\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} diff --git a/langs/tr/tutorials/introduction_basics/lesson.md b/langs/tr/tutorials/introduction_basics/lesson.md new file mode 100644 index 00000000..ead15151 --- /dev/null +++ b/langs/tr/tutorials/introduction_basics/lesson.md @@ -0,0 +1,29 @@ +# Introduction + +This interactive guide will walk you through Solid's main features. You can also refer to the API and guides to learn more about how Solid works. + +You can also check out our new beginner tutorial (work-in-progress!) [here](https://docs.solidjs.com/tutorials/getting-started-with-solid/). + +# What is Solid? + +Solid is a JavaScript framework for making interactive web applications. +With Solid, you can use your existing HTML and JavaScript knowledge to build components that can be reused throughout your app. +Solid provides the tools to enhance your components with _reactivity_: declarative JavaScript code that links the user interface with the data that it uses and creates. + +# Anatomy of a Solid App + +A Solid App is composed of functions that we call components. Take a look at the `HelloWorld` function on the right: it directly returns a `div`! This mix of HTML and JavaScript is called JSX. Solid ships with a compiler that turns these tags into DOM nodes later on. + +JSX allows you to use most HTML elements in our app, but it also lets you create new elements. Once we've declared our `HelloWorld` function, we can use it as a `` tag throughout our app. + +The entry point for any Solid App is the `render` function. It takes 2 arguments, a function wrapping our application code and an existing element in the HTML to mount to: + +```jsx +render(() => , document.getElementById("app")); +``` + +# Leveraging this Tutorial + +Each lesson in the tutorial presents a Solid feature and a scenario to try it out. At any point you can click the solve button to see the solution or click reset to start over. The code editor itself has a console and an output tab where you can see the compiled output generated from your code. Look at it if you are curious to see how Solid generates code. + +Have fun! diff --git a/langs/tr/tutorials/introduction_basics/solved.json b/langs/tr/tutorials/introduction_basics/solved.json new file mode 100644 index 00000000..31200eb3 --- /dev/null +++ b/langs/tr/tutorials/introduction_basics/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\n\nfunction HelloWorld() {\n return
    Hello Solid World!
    ;\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} diff --git a/langs/tr/tutorials/introduction_components/lesson.json b/langs/tr/tutorials/introduction_components/lesson.json new file mode 100644 index 00000000..3e0d70ed --- /dev/null +++ b/langs/tr/tutorials/introduction_components/lesson.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\n\nfunction App() {\n return (\n

    This is a Header

    \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "nested", + "content": "export default () =>

    This is a Paragraph

    " + } + ] +} diff --git a/langs/tr/tutorials/introduction_components/lesson.md b/langs/tr/tutorials/introduction_components/lesson.md new file mode 100644 index 00000000..03568b74 --- /dev/null +++ b/langs/tr/tutorials/introduction_components/lesson.md @@ -0,0 +1,24 @@ +As you build your applications, you will want to break apart your code for better modularity and reusability. In Solid, the main way of doing that is by creating components. + +Components are just functions like the `HelloWorld()` one we've been using so far. What makes them special is that they typically return JSX and can be called by JSX in other components. + +In this example, let's add our `Nested` component to our app. We've defined it in another file, though you can put multiple components in the same file. First we must import it: + +```js +import Nested from "./nested"; +``` + +Then we need to add the component to our JSX. Like before, we now have multiple elements we want to return, so we wrap them in a Fragment: + +```jsx +function App() { + return ( + <> +

    This is a Header

    + + + ); +} +``` + +When the parent component first renders, it will execute the `Nested()` function and won't call it ever again. All updates are applied by Solid’s reactivity system which we will cover in the next couple of lessons. diff --git a/langs/tr/tutorials/introduction_components/solved.json b/langs/tr/tutorials/introduction_components/solved.json new file mode 100644 index 00000000..3a259599 --- /dev/null +++ b/langs/tr/tutorials/introduction_components/solved.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport Nested from \"./nested\";\n\nfunction App() {\n return (\n <>\n

    This is a Header

    \n \n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "nested", + "content": "export default () =>

    This is a Paragraph

    " + } + ] +} diff --git a/langs/tr/tutorials/introduction_derived/lesson.json b/langs/tr/tutorials/introduction_derived/lesson.json new file mode 100644 index 00000000..266f7a15 --- /dev/null +++ b/langs/tr/tutorials/introduction_derived/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nfunction Counter() {\n const [count, setCount] = createSignal(0);\n\n setInterval(() => setCount(count() + 1), 1000);\n\n return
    Count: {count()}
    ;\n}\n\nrender(() => , document.getElementById('app'));" + } + ] +} diff --git a/langs/tr/tutorials/introduction_derived/lesson.md b/langs/tr/tutorials/introduction_derived/lesson.md new file mode 100644 index 00000000..38650c11 --- /dev/null +++ b/langs/tr/tutorials/introduction_derived/lesson.md @@ -0,0 +1,16 @@ +We've seen that whenever we access a signal in JSX, it will automatically update the view when that signal changes. But the component function itself only executes once. + +We can create new expressions that depend on signals by wrapping a signal in a function. A function that accesses a signal is effectively also a signal: when its wrapped signal changes it will in turn update its readers. + +Let's update our Counter to count by 2 by introducing a `doubleCount` function: + +```jsx +const doubleCount = () => count() * 2; +``` + +We can then call `doubleCount` just like a signal in our JSX: +```jsx +return
    Count: {doubleCount()}
    ; +``` + +We call functions like these _derived signals_ because they gain their reactivity from the signal they access. They don't themselves store a value (if you create a derived signal but never call it, it will be stripped from Solid's output like any unused function) but they'll update any effects that depend on them, and they'll trigger a rerender if included in a view. \ No newline at end of file diff --git a/langs/tr/tutorials/introduction_derived/solved.json b/langs/tr/tutorials/introduction_derived/solved.json new file mode 100644 index 00000000..71bf7c80 --- /dev/null +++ b/langs/tr/tutorials/introduction_derived/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nfunction Counter() {\n const [count, setCount] = createSignal(0);\n const doubleCount = () => count() * 2;\n\n setInterval(() => setCount(count() + 1), 1000);\n\n return
    Count: {doubleCount()}
    ;\n}\n\nrender(() => , document.getElementById('app'));" + } + ] +} diff --git a/langs/tr/tutorials/introduction_effects/lesson.json b/langs/tr/tutorials/introduction_effects/lesson.json new file mode 100644 index 00000000..f5176ea0 --- /dev/null +++ b/langs/tr/tutorials/introduction_effects/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\nimport { createSignal, createEffect } from 'solid-js';\n\nfunction Counter() {\n const [count, setCount] = createSignal(0);\n\n return ;\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} diff --git a/langs/tr/tutorials/introduction_effects/lesson.md b/langs/tr/tutorials/introduction_effects/lesson.md new file mode 100644 index 00000000..e422d495 --- /dev/null +++ b/langs/tr/tutorials/introduction_effects/lesson.md @@ -0,0 +1,21 @@ +Signals are trackable values, but they are only one half of the equation. To complement those are observers that can be updated by those trackable values. An _effect_ is one such observer; it runs a side effect that depends on signals. + +An effect can be created by importing `createEffect` from `solid-js` and providing it a function. The effect automatically subscribes to any signal that is read during the function's execution and reruns when any of them change. + +So let's create an Effect that reruns whenever `count` changes: + +```jsx +createEffect(() => { + console.log("The count is now", count()); +}); +``` + +To update our `count` Signal, we'll attach a click handler on our button: + +```jsx + +``` + +Now clicking the button writes to the console. This is a relatively simple example, but to understand how Solid works, you should imagine that every expression in JSX is its own effect that re-executes whenever its dependent signals change. This is how all rendering works in Solid: from Solid's perspective, *all rendering is just a side effect of the reactive system*. + +> Effects that developers create with `createEffect` run after rendering has completed and are mostly used for scheduling updates that interact with the DOM. If you want to modify the DOM earlier, use [`createRenderEffect`](https://www.solidjs.com/docs/latest/api#createrendereffect). \ No newline at end of file diff --git a/langs/tr/tutorials/introduction_effects/solved.json b/langs/tr/tutorials/introduction_effects/solved.json new file mode 100644 index 00000000..8732c699 --- /dev/null +++ b/langs/tr/tutorials/introduction_effects/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\nimport { createSignal, createEffect } from 'solid-js';\n\nfunction Counter() {\n const [count, setCount] = createSignal(0);\n createEffect(() => {\n console.log(\"The count is now\", count());\n });\n\n return ;\n}\n\nrender(() => , document.getElementById('app'));\n" + } + ] +} diff --git a/langs/tr/tutorials/introduction_jsx/lesson.json b/langs/tr/tutorials/introduction_jsx/lesson.json new file mode 100644 index 00000000..5837d9df --- /dev/null +++ b/langs/tr/tutorials/introduction_jsx/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\n\nfunction HelloWorld() {\n const name = \"Solid\";\n const svg = (
    Replace me with an svg
    )\n\n return (\n <>\n
    Hello {name}!
    \n {svg}\n \n )\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} \ No newline at end of file diff --git a/langs/tr/tutorials/introduction_jsx/lesson.md b/langs/tr/tutorials/introduction_jsx/lesson.md new file mode 100644 index 00000000..5e8afc17 --- /dev/null +++ b/langs/tr/tutorials/introduction_jsx/lesson.md @@ -0,0 +1,31 @@ +JSX is the HTML-like syntax we've seen inside these examples and is core to building components in Solid. +JSX adds dynamic expressions that allow you to reference variables and functions within your HTML by using the `{ } ` syntax. +In this example, we include the string `name` in our HTML using `{name}` inside a div. In the same way, we include an HTML element that was directly assigned to the `svg` variable. + +Unlike some other frameworks that use JSX, Solid attempts to stay as close to HTML standards as possible, allowing copy and paste from answers on Stack Overflow or from template builders from your designers. + +There are 3 main differences between JSX and HTML that prevent JSX from being seen as a superset of HTML: +1. JSX does not have void elements. This means that all elements must have a closing tag or self-close. Keep this in mind when copying over elements like `` or `
    `. +2. JSX must return a single Element. To represent multiple top level elements, use a Fragment element: + + ```jsx + <> +

    Title

    +

    Some Text

    + + ``` +3. JSX doesn't support HTML Comments `` or special tags like ``. + +But JSX does support SVG. Let's try copying some SVG right into our component: +```jsx + + + + + + + + + Sorry but this browser does not support inline SVG. + +``` diff --git a/langs/tr/tutorials/introduction_jsx/solved.json b/langs/tr/tutorials/introduction_jsx/solved.json new file mode 100644 index 00000000..4a1bd44a --- /dev/null +++ b/langs/tr/tutorials/introduction_jsx/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\n\nfunction HelloWorld() {\n const name = \"Solid\";\n const svg = (\n \n \n \n \n \n \n \n \n Sorry but this browser does not support inline SVG.\n \n );\n\n return (\n <>\n
    Hello {name}!
    \n {svg}\n \n )\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} \ No newline at end of file diff --git a/langs/tr/tutorials/introduction_memos/lesson.json b/langs/tr/tutorials/introduction_memos/lesson.json new file mode 100644 index 00000000..cc7c690a --- /dev/null +++ b/langs/tr/tutorials/introduction_memos/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\nimport { createSignal, createMemo } from 'solid-js';\n\nfunction fibonacci(num) {\n if (num <= 1) return 1;\n\n return fibonacci(num - 1) + fibonacci(num - 2);\n}\n\nfunction Counter() {\n const [count, setCount] = createSignal(10);\n const fib = () => fibonacci(count());\n\n return (\n <>\n \n
    1. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    2. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    3. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    4. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    5. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    6. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    7. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    8. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    9. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    10. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n \n );\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} diff --git a/langs/tr/tutorials/introduction_memos/lesson.md b/langs/tr/tutorials/introduction_memos/lesson.md new file mode 100644 index 00000000..ec135072 --- /dev/null +++ b/langs/tr/tutorials/introduction_memos/lesson.md @@ -0,0 +1,16 @@ +Most of the time, composing derived signals is sufficient. However, it is sometimes beneficial to cache values in order to reduce duplicated work. We can use memos to evaluate a function and store the result until its dependencies change. This is great for caching calculations for effects that have other dependencies and mitigating the work required for expensive operations like DOM node creation. + +Memos are both an observer, like an effect, and a read-only signal. Since they are aware of both their dependencies and their observers, they can ensure that they run only once for any change. This makes them preferable to registering effects that write to signals. Generally, what can be derived, should be derived. + +Creating a Memo is as simple as passing a function to `createMemo`, imported from `solid-js`. In the example, recalculating the value gets increasingly more expensive with each click. If we wrap it in `createMemo`, it recalculates only once per click: + +```jsx +const fib = createMemo(() => fibonacci(count())); +``` +Place a `console.log` inside the `fib` function to confirm how often it runs: +```jsx +const fib = createMemo(() => { + console.log("Calculating Fibonacci"); + return fibonacci(count()); +}); +``` diff --git a/langs/tr/tutorials/introduction_memos/solved.json b/langs/tr/tutorials/introduction_memos/solved.json new file mode 100644 index 00000000..bb06d4fe --- /dev/null +++ b/langs/tr/tutorials/introduction_memos/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from 'solid-js/web';\nimport { createSignal, createMemo } from 'solid-js';\n\nfunction fibonacci(num) {\n if (num <= 1) return 1;\n\n return fibonacci(num - 1) + fibonacci(num - 2);\n}\n\nfunction Counter() {\n const [count, setCount] = createSignal(10);\n const fib = createMemo(() => {\n console.log('Calculating Fibonacci');\n return fibonacci(count());\n });\n\n return (\n <>\n \n
    1. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    2. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    3. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    4. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    5. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    6. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    7. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    8. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    9. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n
    10. {fib()} {fib()} {fib()} {fib()} {fib()}
    \n \n );\n}\n\nrender(() => , document.getElementById('app'))\n" + } + ] +} diff --git a/langs/tr/tutorials/introduction_signals/lesson.json b/langs/tr/tutorials/introduction_signals/lesson.json new file mode 100644 index 00000000..47186a77 --- /dev/null +++ b/langs/tr/tutorials/introduction_signals/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nfunction Counter() {\n return
    Count: 0
    ;\n}\n\nrender(() => , document.getElementById('app'));" + } + ] +} diff --git a/langs/tr/tutorials/introduction_signals/lesson.md b/langs/tr/tutorials/introduction_signals/lesson.md new file mode 100644 index 00000000..465ba9db --- /dev/null +++ b/langs/tr/tutorials/introduction_signals/lesson.md @@ -0,0 +1,29 @@ +_Signals_ are the cornerstone of reactivity in Solid. They contain values that change over time; when you change a signal's value, it automatically updates anything that uses it. + +To create a signal, let's import `createSignal` from `solid-js` and call it from our Counter component like this: +```jsx +const [count, setCount] = createSignal(0); +``` + +The argument passed to the create call is the initial value, and the return value is an array with two functions, a getter and a setter. By [destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment), we can name these functions whatever we like. In this case, we name the getter `count` and the setter `setCount`. + +It is important to notice that the first returned value is a getter (a function returning the current value) and not the value itself. This is because the framework needs to keep track of where that signal is read so it can update things accordingly. + +In this lesson, we'll use JavaScript's `setInterval` function to create a periodically incrementing counter. We can update our `count` signal every second by adding this code to our Counter component: + +```jsx +setInterval(() => setCount(count() + 1), 1000); +``` + +Each tick, we read the previous count, add 1, and set the new value. + +> Solid's signals also accept a function form where you can use the previous value to set the next value. +> ```jsx +> setCount(c => c + 1); +> ``` + +Finally, we need to read the signal in our JSX code: + +```jsx +return
    Count: {count()}
    ; +``` diff --git a/langs/tr/tutorials/introduction_signals/solved.json b/langs/tr/tutorials/introduction_signals/solved.json new file mode 100644 index 00000000..266f7a15 --- /dev/null +++ b/langs/tr/tutorials/introduction_signals/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nfunction Counter() {\n const [count, setCount] = createSignal(0);\n\n setInterval(() => setCount(count() + 1), 1000);\n\n return
    Count: {count()}
    ;\n}\n\nrender(() => , document.getElementById('app'));" + } + ] +} diff --git a/langs/tr/tutorials/lifecycles_oncleanup/lesson.json b/langs/tr/tutorials/lifecycles_oncleanup/lesson.json new file mode 100644 index 00000000..21ee04ad --- /dev/null +++ b/langs/tr/tutorials/lifecycles_oncleanup/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, onCleanup } from \"solid-js\";\n\nfunction Counter() {\n const [count, setCount] = createSignal(0);\n\n setInterval(() => setCount(count() + 1), 1000);\n\n return
    Count: {count()}
    ;\n}\n\nrender(() => , document.getElementById('app'));" + } + ] +} diff --git a/langs/tr/tutorials/lifecycles_oncleanup/lesson.md b/langs/tr/tutorials/lifecycles_oncleanup/lesson.md new file mode 100644 index 00000000..0fdc6207 --- /dev/null +++ b/langs/tr/tutorials/lifecycles_oncleanup/lesson.md @@ -0,0 +1,10 @@ +Some frameworks pair their cleanup methods as return values of their side effects or lifecycle methods. Since everything in a Solid render tree is living inside a (possibly inert) Effect and can be nested, we made `onCleanup` a first-class method. You can call it at any scope and it will run when that scope is triggered to re-evaluate and when it is finally disposed. + +Use it in your components or in your Effects. Use it in your custom directives. Use it pretty much anywhere that is part of the synchronous execution of the reactive system. + +The Signal example from the introduction never cleaned up after itself. Let's fix that by replacing the `setInterval` call with this: + +```js +const timer = setInterval(() => setCount(count() + 1), 1000); +onCleanup(() => clearInterval(timer)); +``` \ No newline at end of file diff --git a/langs/tr/tutorials/lifecycles_oncleanup/solved.json b/langs/tr/tutorials/lifecycles_oncleanup/solved.json new file mode 100644 index 00000000..f7fde7ca --- /dev/null +++ b/langs/tr/tutorials/lifecycles_oncleanup/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, onCleanup } from \"solid-js\";\n\nfunction Counter() {\n const [count, setCount] = createSignal(0);\n\n const timer = setInterval(() => setCount(count() + 1), 1000);\n onCleanup(() => clearInterval(timer));\n\n return
    Count: {count()}
    ;\n}\n\nrender(() => , document.getElementById('app'));" + } + ] +} diff --git a/langs/tr/tutorials/lifecycles_onmount/lesson.json b/langs/tr/tutorials/lifecycles_onmount/lesson.json new file mode 100644 index 00000000..77dd5843 --- /dev/null +++ b/langs/tr/tutorials/lifecycles_onmount/lesson.json @@ -0,0 +1,13 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, onMount, For } from \"solid-js\";\nimport \"./styles.css\";\n\nfunction App() {\n const [photos, setPhotos] = createSignal([]);\n\n return <>\n

    Photo album

    \n\n
    \n Loading...

    }>{ photo =>\n
    \n {photo.title}\n
    {photo.title}
    \n
    \n }
    \n
    \n ;\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "styles", + "type": "css", + "content": ".photos {\n width: 100%;\n display: grid;\n grid-template-columns: repeat(5, 1fr);\n grid-gap: 8px;\n}\n\nfigure, img {\n width: 100%;\n margin: 0;\n}" + } + ] +} diff --git a/langs/tr/tutorials/lifecycles_onmount/lesson.md b/langs/tr/tutorials/lifecycles_onmount/lesson.md new file mode 100644 index 00000000..c84128b3 --- /dev/null +++ b/langs/tr/tutorials/lifecycles_onmount/lesson.md @@ -0,0 +1,16 @@ +There are only a few Lifecycle functions in Solid as everything lives and dies by the reactive system. The reactive system is created and updates synchronously, so the only scheduling comes down to Effects which are pushed to the end of the update. + +We've found that developers doing basic tasks don't often think this way, so to make things a +little easier we've made an alias, `onMount`. `onMount` is just a `createEffect` call that is +non-tracking, which means it never re-runs. It is just an Effect call but you can use it with confidence +that it will run only once for your component, once all initial rendering is done. + +Let's use the `onMount` hook to fetch some photos: +```js +onMount(async () => { + const res = await fetch(`https://jsonplaceholder.typicode.com/photos?_limit=20`); + setPhotos(await res.json()); +}); +``` + +Lifecycles are only run in the browser, so putting code in `onMount` has the benefit of not running on the server during SSR. Even though we are doing data fetching in this example, usually we use Solid's resources for true server/browser coordination. diff --git a/langs/tr/tutorials/lifecycles_onmount/solved.json b/langs/tr/tutorials/lifecycles_onmount/solved.json new file mode 100644 index 00000000..1638c344 --- /dev/null +++ b/langs/tr/tutorials/lifecycles_onmount/solved.json @@ -0,0 +1,13 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, onMount, For } from \"solid-js\";\nimport \"./styles.css\";\n\nfunction App() {\n const [photos, setPhotos] = createSignal([]);\n\n onMount(async () => {\n const res = await fetch(`https://jsonplaceholder.typicode.com/photos?_limit=20`);\n setPhotos(await res.json());\n });\n\n return <>\n

    Photo album

    \n\n
    \n Loading...

    }>{ photo =>\n
    \n {photo.title}\n
    {photo.title}
    \n
    \n }
    \n
    \n ;\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "styles", + "type": "css", + "content": ".photos {\n width: 100%;\n display: grid;\n grid-template-columns: repeat(5, 1fr);\n grid-gap: 8px;\n}\n\nfigure, img {\n width: 100%;\n margin: 0;\n}" + } + ] +} diff --git a/langs/tr/tutorials/props_children/lesson.json b/langs/tr/tutorials/props_children/lesson.json new file mode 100644 index 00000000..4d4051be --- /dev/null +++ b/langs/tr/tutorials/props_children/lesson.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, For } from \"solid-js\";\n\nimport ColoredList from \"./colored-list\";\n\nfunction App() {\n const [color, setColor] = createSignal(\"purple\");\n\n return <>\n \n {item =>
    {item}
    }
    \n
    \n \n ;\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "colored-list", + "content": "import { createEffect, children } from \"solid-js\";\n\nexport default function ColoredList(props) {\n return <>{props.children}\n}" + } + ] +} diff --git a/langs/tr/tutorials/props_children/lesson.md b/langs/tr/tutorials/props_children/lesson.md new file mode 100644 index 00000000..d277a2be --- /dev/null +++ b/langs/tr/tutorials/props_children/lesson.md @@ -0,0 +1,33 @@ +Part of what makes Solid so performant is that our components are basically just function calls. The way we propagate updates is that the compiler wraps potentially reactive expressions in object getters. You can picture the compiler to output: + +```jsx +// this JSX + + + + +// to become +MyComp({ + get dynamic() { return mySignal() }, + get children() { return Child() } +}); +``` +This means that these props are evaluated lazily. Their access is deferred until where they are used. This retains reactivity without introducing extraneous wrappers or synchronization. However, it means that repeat access can lead to recreating child components or elements. + +The vast majority of the time you will just be inserting props into the JSX so there is no problem. However, when you work with children, you need to be careful to avoid creating the children multiple times. + +For that reason, Solid has the `children` helper. This method both creates a memo around the `children` prop and resolves any nested child reactive references so that you can interact with the children directly. + +In the example, we have a dynamic list and we want to set the items' `color` style property. If we interacted with `props.children` directly, not only would we create the nodes multiple times, but we'd find `props.children` to be a function, the Memo returned from ``. + +Instead let's use the `children` helper inside `colored-list.tsx`: +```jsx +export default function ColoredList(props) { + const c = children(() => props.children); + return <>{c()} +} +``` +Now to update our elements, let's create an Effect: +```jsx +createEffect(() => c().forEach(item => item.style.color = props.color)); +``` diff --git a/langs/tr/tutorials/props_children/solved.json b/langs/tr/tutorials/props_children/solved.json new file mode 100644 index 00000000..7f7aa8d5 --- /dev/null +++ b/langs/tr/tutorials/props_children/solved.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, For } from \"solid-js\";\n\nimport ColoredList from \"./colored-list\";\n\nfunction App() {\n const [color, setColor] = createSignal(\"purple\");\n\n return <>\n \n {item =>
    {item}
    }
    \n
    \n \n ;\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "colored-list", + "content": "import { createEffect, children } from \"solid-js\";\n\nexport default function ColoredList(props) {\n const c = children(() => props.children);\n createEffect(() => c().forEach(item => item.style.color = props.color));\n return <>{c()}\n}" + } + ] +} diff --git a/langs/tr/tutorials/props_defaults/lesson.json b/langs/tr/tutorials/props_defaults/lesson.json new file mode 100644 index 00000000..671b1e57 --- /dev/null +++ b/langs/tr/tutorials/props_defaults/lesson.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nimport Greeting from \"./greeting\";\n\nfunction App() {\n const [name, setName] = createSignal();\n\n return <>\n \n \n \n \n ;\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "greeting", + "content": "import { mergeProps } from \"solid-js\";\n\nexport default function Greeting(props) {\n return

    {props.greeting || \"Hi\"} {props.name || \"John\"}

    \n}" + } + ] +} diff --git a/langs/tr/tutorials/props_defaults/lesson.md b/langs/tr/tutorials/props_defaults/lesson.md new file mode 100644 index 00000000..2dfcc9c9 --- /dev/null +++ b/langs/tr/tutorials/props_defaults/lesson.md @@ -0,0 +1,13 @@ +Props are what we call the object that is passed to our component function on execution that represents all the attributes bound to its JSX. Props objects are readonly and have reactive properties which are wrapped in Object getters. This allows them to have a consistent form regardless of whether the caller used signals, signal expressions, or static values. You access them by `props.propName`. + +For this reason it is also very important to not just destructure props objects, as that would lose reactivity if not done within a tracking scope. In general accessing properties on the props object outside of Solid's primitives or JSX can lose reactivity. This applies not just to destructuring, but also to spreads and functions like `Object.assign`. + +Solid has a few utilities to help us when working with props. The first is `mergeProps`, which merges potentially reactive objects together (like a nondestructive `Object.assign`) without losing reactivity. The most common case is when setting default props for our components. + +In the example, in `greetings.tsx`, we inlined the defaults in the template, but we could also use `mergeProps` to keep reactive updates even when setting defaults: + +```jsx +const merged = mergeProps({ greeting: "Hi", name: "John" }, props); + +return

    {merged.greeting} {merged.name}

    +``` diff --git a/langs/tr/tutorials/props_defaults/solved.json b/langs/tr/tutorials/props_defaults/solved.json new file mode 100644 index 00000000..17361fc1 --- /dev/null +++ b/langs/tr/tutorials/props_defaults/solved.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nimport Greeting from \"./greeting\";\n\nfunction App() {\n const [name, setName] = createSignal();\n\n return <>\n \n \n \n \n ;\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "greeting", + "content": "import { mergeProps } from \"solid-js\";\n\nexport default function Greeting(props) {\n const merged = mergeProps({ greeting: \"Hi\", name: \"John\" }, props);\n\n return

    {merged.greeting} {merged.name}

    \n}" + } + ] +} diff --git a/langs/tr/tutorials/props_split/lesson.json b/langs/tr/tutorials/props_split/lesson.json new file mode 100644 index 00000000..0439f16a --- /dev/null +++ b/langs/tr/tutorials/props_split/lesson.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nimport Greeting from \"./greeting\";\n\nfunction App() {\n const [name, setName] = createSignal(\"Jakob\");\n\n return <>\n \n \n ;\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "greeting", + "content": "import { splitProps } from \"solid-js\";\n\nexport default function Greeting(props) {\n const { greeting, name, ...others } = props;\n return

    {greeting} {name}

    \n}" + } + ] +} diff --git a/langs/tr/tutorials/props_split/lesson.md b/langs/tr/tutorials/props_split/lesson.md new file mode 100644 index 00000000..1593e718 --- /dev/null +++ b/langs/tr/tutorials/props_split/lesson.md @@ -0,0 +1,26 @@ +Merging props isn't the only props operation we might want to do. + +Often, we want to split props into groups, so that we can use some of them on +the current component but split off others to pass through to child components. + +For this purpose, Solid has [`splitProps`](/docs/latest/api#splitprops). It +takes the props object +and +one or more arrays of keys that we want to extract into their own props objects. It returns an array of props objects, one per array of specified keys, plus one props object with any remaining keys. All returned objects preserve reactivity. + +Our example doesn't update when we set the name because of lost reactivity when we destructure in `greeting.tsx`: +```jsx +export default function Greeting(props) { + const { greeting, name, ...others } = props; + return

    {greeting} {name}

    +} +``` + +Instead, we can maintain reactivity with `splitProps`: +```jsx +export default function Greeting(props) { + const [local, others] = splitProps(props, ["greeting", "name"]); + return

    {local.greeting} {local.name}

    +} +``` +Now the button works as expected. \ No newline at end of file diff --git a/langs/tr/tutorials/props_split/solved.json b/langs/tr/tutorials/props_split/solved.json new file mode 100644 index 00000000..a6026a0e --- /dev/null +++ b/langs/tr/tutorials/props_split/solved.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal } from \"solid-js\";\n\nimport Greeting from \"./greeting\";\n\nfunction App() {\n const [name, setName] = createSignal(\"Jakob\");\n\n return <>\n \n \n ;\n}\n\nrender(() => , document.getElementById('app'));" + }, + { + "name": "greeting", + "content": "import { splitProps } from \"solid-js\";\n\nexport default function Greeting(props) {\n const [local, others] = splitProps(props, [\"greeting\", \"name\"]);\n return

    {local.greeting} {local.name}

    \n}" + } + ] +} \ No newline at end of file diff --git a/langs/tr/tutorials/reactivity_batch/lesson.json b/langs/tr/tutorials/reactivity_batch/lesson.json new file mode 100644 index 00000000..29a90329 --- /dev/null +++ b/langs/tr/tutorials/reactivity_batch/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, batch } from \"solid-js\";\n\nconst App = () => {\n const [firstName, setFirstName] = createSignal(\"John\");\n const [lastName, setLastName] = createSignal(\"Smith\");\n const fullName = () => {\n console.log(\"Running FullName\");\n return `${firstName()} ${lastName()}`\n } \n const updateNames = () => {\n console.log(\"Button Clicked\");\n setFirstName(firstName() + \"n\");\n setLastName(lastName() + \"!\");\n }\n \n return \n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/reactivity_batch/lesson.md b/langs/tr/tutorials/reactivity_batch/lesson.md new file mode 100644 index 00000000..a8789813 --- /dev/null +++ b/langs/tr/tutorials/reactivity_batch/lesson.md @@ -0,0 +1,16 @@ +Solid's reactivity is synchronous which means, by the next line after any change, the DOM will have updated. And for the most part this is perfectly fine, as Solid's granular rendering is just a propagation of the update in the reactive system. Unrelated changes "rendering" twice don't actually mean wasted work. + +What if the changes are related? Solid's `batch` helper allows to queue up multiple changes and then apply them all at the same time before notifying their observers. + +In this example, we are assigning both names on a button click and this triggers our rendered update twice. You can see the logs in the console when you click the button. So let's wrap the `set` calls in a batch. + +```js + const updateNames = () => { + console.log("Button Clicked"); + batch(() => { + setFirstName(firstName() + "n"); + setLastName(lastName() + "!"); + }) + } +``` +And that's it. Now we only notify once for the whole changeset. \ No newline at end of file diff --git a/langs/tr/tutorials/reactivity_batch/solved.json b/langs/tr/tutorials/reactivity_batch/solved.json new file mode 100644 index 00000000..bf41d10a --- /dev/null +++ b/langs/tr/tutorials/reactivity_batch/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, batch } from \"solid-js\";\n\nconst App = () => {\n const [firstName, setFirstName] = createSignal(\"John\");\n const [lastName, setLastName] = createSignal(\"Smith\");\n const fullName = () => {\n console.log(\"Running FullName\");\n return `${firstName()} ${lastName()}`\n } \n const updateNames = () => {\n console.log(\"Button Clicked\");\n batch(() => {\n setFirstName(firstName() + \"n\");\n setLastName(lastName() + \"!\");\n })\n }\n \n return \n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/reactivity_on/lesson.json b/langs/tr/tutorials/reactivity_on/lesson.json new file mode 100644 index 00000000..22900826 --- /dev/null +++ b/langs/tr/tutorials/reactivity_on/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, createEffect, on } from \"solid-js\";\n\nconst App = () => {\n const [a, setA] = createSignal(1);\n const [b, setB] = createSignal(1);\n\n createEffect(() => {\n console.log(a(), b());\n });\n\n return <>\n \n \n \n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/reactivity_on/lesson.md b/langs/tr/tutorials/reactivity_on/lesson.md new file mode 100644 index 00000000..1d9deffc --- /dev/null +++ b/langs/tr/tutorials/reactivity_on/lesson.md @@ -0,0 +1,9 @@ +For convenience, Solid has an `on` helper that enables setting explicit dependencies for our computations. This is mostly used as a terse way to be even more explicit about which Signals are tracked (and not track any other Signals, even if they are read). In addition, `on` provides a `defer` option that allows the computation not to execute immediately and only run on first change. + +Let's have our Effect run only when `a` updates, and defer execution until the value changes: + +```js +createEffect(on(a, (a) => { + console.log(a, b()); +}, { defer: true })); +``` diff --git a/langs/tr/tutorials/reactivity_on/solved.json b/langs/tr/tutorials/reactivity_on/solved.json new file mode 100644 index 00000000..21608f91 --- /dev/null +++ b/langs/tr/tutorials/reactivity_on/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, createEffect, on } from \"solid-js\";\n\nconst App = () => {\n const [a, setA] = createSignal(1);\n const [b, setB] = createSignal(1);\n\n createEffect(on(a, (a) => {\n console.log(a, b());\n }, { defer: true }));\n\n return <>\n \n \n \n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/reactivity_untrack/lesson.json b/langs/tr/tutorials/reactivity_untrack/lesson.json new file mode 100644 index 00000000..01a332e0 --- /dev/null +++ b/langs/tr/tutorials/reactivity_untrack/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, createEffect, untrack } from \"solid-js\";\n\nconst App = () => {\n const [a, setA] = createSignal(1);\n const [b, setB] = createSignal(1);\n\n createEffect(() => {\n console.log(a(), b());\n });\n\n return <>\n \n \n \n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/reactivity_untrack/lesson.md b/langs/tr/tutorials/reactivity_untrack/lesson.md new file mode 100644 index 00000000..061f55fd --- /dev/null +++ b/langs/tr/tutorials/reactivity_untrack/lesson.md @@ -0,0 +1,12 @@ +It's sometimes desirable to have Signal reads not be tracked, even inside a reactive context. Solid provides the `untrack` helper as a way to prevent the wrapping computation from tracking any reads. + +Let's suppose we did not want to log in our example when `b` changes. We can untrack the `b` signal by changing our effect to the following: + +```js +createEffect(() => { + console.log(a(), untrack(b)); +}); +``` +Since Signals are functions, they can be passed directly, but `untrack` can wrap functions with more complex behavior. + +Even though `untrack` disables tracking of reads, it has no effect on writes which still happen and notify their observers. diff --git a/langs/tr/tutorials/reactivity_untrack/solved.json b/langs/tr/tutorials/reactivity_untrack/solved.json new file mode 100644 index 00000000..0f66193d --- /dev/null +++ b/langs/tr/tutorials/reactivity_untrack/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { createSignal, createEffect, untrack } from \"solid-js\";\n\nconst App = () => {\n const [a, setA] = createSignal(1);\n const [b, setB] = createSignal(1);\n\n createEffect(() => {\n console.log(a(), untrack(b));\n });\n\n return <>\n \n \n \n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/stores_context/lesson.json b/langs/tr/tutorials/stores_context/lesson.json new file mode 100644 index 00000000..5c8d5014 --- /dev/null +++ b/langs/tr/tutorials/stores_context/lesson.json @@ -0,0 +1,16 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport Nested from \"./nested\";\nimport { CounterProvider } from \"./counter\";\n\nfunction App() {\n return <>\n

    Welcome to Counter App

    \n \n \n};\n\nrender(() => , document.getElementById(\"app\"));" + }, + { + "name": "nested", + "content": "import { useCounter } from \"./counter\";\n\nexport default function Nested() {\n return (\n <>\n
    0
    \n \n \n \n );\n};" + }, + { + "name": "counter", + "content": "import { createSignal, createContext, useContext } from \"solid-js\";\n\nconst CounterContext = createContext();\n\nexport function CounterProvider(props) {\n const [count, setCount] = createSignal(props.count || 0),\n counter = [\n count,\n {\n increment() {\n setCount(c => c + 1);\n },\n decrement() {\n setCount(c => c - 1);\n }\n }\n ];\n\n return (\n \n {props.children}\n \n );\n}\n\nexport function useCounter() { return useContext(CounterContext); }" + } + ] +} diff --git a/langs/tr/tutorials/stores_context/lesson.md b/langs/tr/tutorials/stores_context/lesson.md new file mode 100644 index 00000000..e76d779e --- /dev/null +++ b/langs/tr/tutorials/stores_context/lesson.md @@ -0,0 +1,28 @@ +Solid provides a Context API to pass data around without relying on passing through props. This is useful for sharing Signals and Stores. Using Context has the benefit of being created as part of the reactive system and managed by it. + +To get started we create a Context object. This object contains a `Provider` component used to inject our data. However, it is common practice to wrap the `Provider` components and `useContext` consumers with versions already configured for the specific Context. + +And that's exactly what we have in this tutorial. You can see the definition for a simple counter store in the `counter.tsx` file. + +To use context, first let's wrap our App component to provide it globally. We will use our wrapped `CounterProvider`. In this case let's give it an initial count of 1. + +```jsx +render(() => ( + + + +), document.getElementById("app")); +``` + +Next we need to consume the counter context in our `nested.tsx` component. We do this by using the wrapped `useCounter` consumer. + +```jsx +const [count, { increment, decrement }] = useCounter(); +return ( + <> +
    {count()}
    + + + +); +``` \ No newline at end of file diff --git a/langs/tr/tutorials/stores_context/solved.json b/langs/tr/tutorials/stores_context/solved.json new file mode 100644 index 00000000..c5967806 --- /dev/null +++ b/langs/tr/tutorials/stores_context/solved.json @@ -0,0 +1,16 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport Nested from \"./nested\";\nimport { CounterProvider } from \"./counter\";\n\nfunction App() {\n return <>\n

    Welcome to Counter App

    \n \n \n};\n\nrender(() => (\n \n \n \n), document.getElementById(\"app\"));" + }, + { + "name": "nested", + "content": "import { useCounter } from \"./counter\";\n\nexport default function Nested() {\n const [count, { increment, decrement }] = useCounter();\n return (\n <>\n
    {count()}
    \n \n \n \n );\n};" + }, + { + "name": "counter", + "content": "import { createSignal, createContext, useContext } from \"solid-js\";\n\nconst CounterContext = createContext();\n\nexport function CounterProvider(props) {\n const [count, setCount] = createSignal(props.count || 0),\n counter = [\n count,\n {\n increment() {\n setCount(c => c + 1);\n },\n decrement() {\n setCount(c => c - 1);\n }\n }\n ];\n\n return (\n \n {props.children}\n \n );\n}\n\nexport function useCounter() { return useContext(CounterContext); }" + } + ] +} diff --git a/langs/tr/tutorials/stores_createstore/lesson.json b/langs/tr/tutorials/stores_createstore/lesson.json new file mode 100644 index 00000000..9a867b74 --- /dev/null +++ b/langs/tr/tutorials/stores_createstore/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { For, createSignal } from \"solid-js\";\nimport { createStore } from \"solid-js/store\";\n\nconst App = () => {\n let input;\n let todoId = 0;\n const [todos, setTodos] = createSignal([])\n const addTodo = (text) => {\n setTodos([...todos(), { id: ++todoId, text, completed: false }]);\n }\n const toggleTodo = (id) => {\n setTodos(todos().map((todo) => (\n todo.id !== id ? todo : { ...todo, completed: !todo.completed }\n )));\n }\n\n return (\n <>\n
    \n \n {\n if (!input.value.trim()) return;\n addTodo(input.value);\n input.value = \"\";\n }}\n >\n Add Todo\n \n
    \n \n {(todo) => {\n const { id, text } = todo;\n console.log(`Creating ${text}`)\n return
    \n \n {text}\n
    \n }}\n
    \n \n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/stores_createstore/lesson.md b/langs/tr/tutorials/stores_createstore/lesson.md new file mode 100644 index 00000000..3b42d41c --- /dev/null +++ b/langs/tr/tutorials/stores_createstore/lesson.md @@ -0,0 +1,29 @@ +Stores are Solid's answer to nested reactivity. They are proxy objects whose properties can be tracked and can contain other objects which automatically become wrapped in proxies themselves, and so on. + +To keep things light, Solid creates underlying Signals only for properties that are accessed under tracking scopes. And so, all Signals in Stores are created lazily as requested. + +The `createStore` call takes the initial value and returns a read/write tuple similar to Signals. The first element is the store proxy which is readonly, and the second is a setter function. + +The setter function in its most basic form takes an object whose properties will be merged with the current state. It also supports path syntax so that we can do nested updates. In this way we can still maintain control of our reactivity but do pinpoint updates. + +> Solid's path syntax has many forms and includes some powerful syntax to do iteration and ranges. Refer to the API documentation for a full reference. + +Let's look at how much easier it is to achieve nested reactivity with a Store. We can replace the initialization of our component with this: + +```js +const [todos, setTodos] = createStore([]); +const addTodo = (text) => { + setTodos([...todos, { id: ++todoId, text, completed: false }]); +}; +const toggleTodo = (id) => { + setTodos( + (todo) => todo.id === id, + "completed", + (completed) => !completed + ); +}; +``` + +We make use of the Store's path syntax with function setters that allow us to take the previous state and return the new state on nested values. + +And that's it. The rest of the template will already react granularly (check the Console on clicking the checkbox). diff --git a/langs/tr/tutorials/stores_createstore/solved.json b/langs/tr/tutorials/stores_createstore/solved.json new file mode 100644 index 00000000..c0bf15e6 --- /dev/null +++ b/langs/tr/tutorials/stores_createstore/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js\/web\";\nimport { For } from \"solid-js\";\nimport { createStore } from \"solid-js\/store\";\n\nconst App = () => {\n let input;\n let todoId = 0;\n const [todos, setTodos] = createStore([]);\n\n const addTodo = (text) => {\n setTodos([...todos, { id: ++todoId, text, completed: false }]);\n }\n\n const toggleTodo = (id) => {\n setTodos(todo => todo.id === id, \"completed\", completed => !completed);\n }\n\n return (\n <>\n
    \n \n {\n if (!input.value.trim()) return;\n addTodo(input.value);\n input.value = \"\";\n }}\n >\n Add Todo\n <\/button>\n <\/div>\n \n {(todo) => {\n const { id, text } = todo;\n console.log(`Creating ${text}`)\n return
    \n \n {text}<\/span>\n <\/div>\n }}\n <\/For>\n <\/>\n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/stores_immutable/lesson.json b/langs/tr/tutorials/stores_immutable/lesson.json new file mode 100644 index 00000000..509de763 --- /dev/null +++ b/langs/tr/tutorials/stores_immutable/lesson.json @@ -0,0 +1,20 @@ +{ + "files": [ + { + "name": "main", + "content": "// @ts-nocheck\nimport { render } from \"solid-js/web\";\nimport { For } from \"solid-js\";\n\nimport useRedux from \"./useRedux\";\nimport reduxStore from \"./store\";\nimport actions from \"./actions\";\n\nconst App = () => {\n const [store, { addTodo, toggleTodo }] = useRedux(\n reduxStore,\n actions\n );\n let input;\n return (\n <>\n
    \n \n {\n if (!input.value.trim()) return;\n addTodo(input.value);\n input.value = \"\";\n }}\n >\n Add Todo\n \n
    \n \n {(todo) => {\n const { id, text } = todo;\n console.log(\"Create\", text)\n return
    \n \n {text}\n
    \n }}\n
    \n \n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + }, + { + "name": "useRedux", + "content": "import { onCleanup } from \"solid-js\";\nimport { createStore, reconcile } from \"solid-js/store\";\n\nexport default function useRedux(store, actions) {\n const [state, setState] = createStore(store.getState());\n const unsubscribe = store.subscribe(\n () => setState(store.getState())\n );\n onCleanup(() => unsubscribe());\n return [\n state,\n mapActions(store, actions)\n ];\n};\n\nfunction mapActions(store, actions) {\n const mapped = {};\n for (const key in actions) {\n mapped[key] = (...args) => store.dispatch(actions[key](...args));\n }\n return mapped;\n}\n" + }, + { + "name": "actions", + "content": "let nextTodoId = 0;\nexport default {\n addTodo: text => ({ type: \"ADD_TODO\", id: ++nextTodoId, text }),\n toggleTodo: id => ({ type: \"TOGGLE_TODO\", id })\n};\n" + }, + { + "name": "store", + "content": "// @ts-nocheck\nimport { createStore } from 'redux';\n\n// todos reducer\nconst todos = (state = { todos: [] }, action) => {\n switch (action.type) {\n case \"ADD_TODO\":\n return { todos: [\n ...state.todos,\n {\n id: action.id,\n text: action.text,\n completed: false\n }\n ]};\n case \"TOGGLE_TODO\":\n return { todos: state.todos.map(todo => \n todo.id === action.id ? { ...todo, completed: !todo.completed } : todo\n )};\n default:\n return state;\n }\n};\n\nexport default createStore(todos);\n" + } + ] +} diff --git a/langs/tr/tutorials/stores_immutable/lesson.md b/langs/tr/tutorials/stores_immutable/lesson.md new file mode 100644 index 00000000..d7ea8f24 --- /dev/null +++ b/langs/tr/tutorials/stores_immutable/lesson.md @@ -0,0 +1,43 @@ +Stores are most often created in Solid using Solid's Store proxies. Sometimes we wish to interface with immutable libraries like Redux, Apollo, or XState and need to perform granular updates against these. + +In the example, we have a basic wrapper around Redux. You can see the implementation in `useRedux.tsx`. The definition of the store and the actions are in the remaining files. + +The core behavior is that we created a Store object and subscribe to the Redux store to update state on update. + +```js +const [state, setState] = createStore(store.getState()); +const unsubscribe = store.subscribe( + () => setState(store.getState()) +); +``` +If you click around the demo adding items and checking them off it seems to work pretty well. However, what isn't obvious is that the rendering is inefficient. Notice the console.log not only on create but whenever you check the box. + +The reason is that Solid doesn't diff by default. It assumes the new item is new and replaces it. If your data changes granularly, you don't need to diff. But what if you do? + +Solid provides a diffing method `reconcile` that enhances the `setStore` call and lets us diff the data from these immutable sources, only notifying the granular updates. + +Let's update that code to: +```js +const [state, setState] = createStore(store.getState()); +const unsubscribe = store.subscribe( + () => setState(reconcile(store.getState())) +); +``` +Now the example works as you'd expect, only running the create code on create. + +This isn't the only way to solve this and you've seen some frameworks have a `key` property on their template loop flows. The problem is that by making that a default part of the templating, you always need to run list reconciliation and always have to diff all the children for potential changes, even in compiled frameworks. A data-centric approach not only makes this applicable outside of templating but makes it opt in. When you consider that internal state management doesn't need this, it means we default to having the best performance. + +Of course, there's no problem using `reconcile` when you need it. Sometimes a simple reducer makes for a great way to organize data updates. `reconcile` shines here, making your own `useReducer` primitive: + +```js +const useReducer = (reducer, state) => { + const [store, setStore] = createStore(state); + const dispatch = (action) => { + state = reducer(state, action); + setStore(reconcile(state)); + } + return [store, dispatch]; +}; +``` + +The behavior of `reconcile` is configurable. A custom `key` can be set and there is a `merge` option which ignores structural cloning and only diffs the leaves. \ No newline at end of file diff --git a/langs/tr/tutorials/stores_immutable/solved.json b/langs/tr/tutorials/stores_immutable/solved.json new file mode 100644 index 00000000..5ac5aa45 --- /dev/null +++ b/langs/tr/tutorials/stores_immutable/solved.json @@ -0,0 +1,20 @@ +{ + "files": [ + { + "name": "main", + "content": "// @ts-nocheck\nimport { render } from \"solid-js/web\";\nimport { For } from \"solid-js\";\n\nimport useRedux from \"./useRedux\";\nimport reduxStore from \"./store\";\nimport actions from \"./actions\";\n\nconst App = () => {\n const [store, { addTodo, toggleTodo }] = useRedux(\n reduxStore,\n actions\n );\n let input;\n return (\n <>\n
    \n \n {\n if (!input.value.trim()) return;\n addTodo(input.value);\n input.value = \"\";\n }}\n >\n Add Todo\n \n
    \n \n {(todo) => {\n const { id, text } = todo;\n console.log(\"Create\", text)\n return
    \n \n {text}\n
    \n }}\n
    \n \n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + }, + { + "name": "useRedux", + "content": "import { onCleanup } from \"solid-js\";\nimport { createStore, reconcile } from \"solid-js/store\";\n\nexport default function useRedux(store, actions) {\n const [state, setState] = createStore(store.getState());\n const unsubscribe = store.subscribe(\n () => setState(reconcile(store.getState()))\n );\n onCleanup(() => unsubscribe());\n return [\n state,\n mapActions(store, actions)\n ];\n};\n\nfunction mapActions(store, actions) {\n const mapped = {};\n for (const key in actions) {\n mapped[key] = (...args) => store.dispatch(actions[key](...args));\n }\n return mapped;\n}\n" + }, + { + "name": "actions", + "content": "let nextTodoId = 0;\nexport default {\n addTodo: text => ({ type: \"ADD_TODO\", id: ++nextTodoId, text }),\n toggleTodo: id => ({ type: \"TOGGLE_TODO\", id })\n};\n" + }, + { + "name": "store", + "content": "// @ts-nocheck\nimport { createStore } from 'redux';\n\n// todos reducer\nconst todos = (state = { todos: [] }, action) => {\n switch (action.type) {\n case \"ADD_TODO\":\n return { todos: [\n ...state.todos,\n {\n id: action.id,\n text: action.text,\n completed: false\n }\n ]};\n case \"TOGGLE_TODO\":\n return { todos: state.todos.map(todo => \n todo.id === action.id ? { ...todo, completed: !todo.completed } : todo\n )};\n default:\n return state;\n }\n};\n\nexport default createStore(todos);\n" + } + ] +} diff --git a/langs/tr/tutorials/stores_mutation/lesson.json b/langs/tr/tutorials/stores_mutation/lesson.json new file mode 100644 index 00000000..c0bf15e6 --- /dev/null +++ b/langs/tr/tutorials/stores_mutation/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js\/web\";\nimport { For } from \"solid-js\";\nimport { createStore } from \"solid-js\/store\";\n\nconst App = () => {\n let input;\n let todoId = 0;\n const [todos, setTodos] = createStore([]);\n\n const addTodo = (text) => {\n setTodos([...todos, { id: ++todoId, text, completed: false }]);\n }\n\n const toggleTodo = (id) => {\n setTodos(todo => todo.id === id, \"completed\", completed => !completed);\n }\n\n return (\n <>\n
    \n \n {\n if (!input.value.trim()) return;\n addTodo(input.value);\n input.value = \"\";\n }}\n >\n Add Todo\n <\/button>\n <\/div>\n \n {(todo) => {\n const { id, text } = todo;\n console.log(`Creating ${text}`)\n return
    \n \n {text}<\/span>\n <\/div>\n }}\n <\/For>\n <\/>\n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/stores_mutation/lesson.md b/langs/tr/tutorials/stores_mutation/lesson.md new file mode 100644 index 00000000..4dff00de --- /dev/null +++ b/langs/tr/tutorials/stores_mutation/lesson.md @@ -0,0 +1,23 @@ +Solid strongly recommends the use of shallow immutable patterns for updating state. By separating reads and writes we maintain better control over the reactivity of our system without the risk of losing track of changes to our proxy when passed through layers of components. This is much more amplified with Stores compared to Signals. + +Sometimes, however, mutation is just easier to reason about. That's why Solid provides an Immer inspired `produce` store modifier that allows you to mutate a writable proxy version of your Store object inside your `setStore` calls. + +This is a nice tool to have to allow small zones of mutation without relinquishing control. Let's use `produce` on our Todos example by replacing our event handler code with: + +```jsx +const addTodo = (text) => { + setTodos( + produce((todos) => { + todos.push({ id: ++todoId, text, completed: false }); + }) + ); +}; +const toggleTodo = (id) => { + setTodos( + (todo) => todo.id === id, + produce((todo) => (todo.completed = !todo.completed)) + ); +}; +``` + +While `produce` with Stores probably handles the vast majority of cases, Solid also has a mutable Store object that is available from `createMutable`. While not the recommended approach for internal APIs, it is sometimes useful for interop or compatibility with 3rd party systems. diff --git a/langs/tr/tutorials/stores_mutation/solved.json b/langs/tr/tutorials/stores_mutation/solved.json new file mode 100644 index 00000000..3f3926d9 --- /dev/null +++ b/langs/tr/tutorials/stores_mutation/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "\/\/ @ts-nocheck\r\nimport { render, For } from \"solid-js\/web\";\r\nimport { createStore, produce } from \"solid-js\/store\";\r\n\r\nconst App = () => {\r\n let input;\r\n let todoId = 0;\r\n const [todos, setTodos] = createStore([]);\r\n const addTodo = (text) => {\r\n setTodos(\r\n produce((todos) => {\r\n todos.push({ id: ++todoId, text, completed: false });\r\n }),\r\n );\r\n };\r\n const toggleTodo = (id) => {\r\n setTodos(\r\n todo => todo.id === id,\r\n produce((todo) => (todo.completed = !todo.completed)),\r\n );\r\n };\r\n\r\n return (\r\n <>\r\n
    \r\n \r\n {\r\n if (!input.value.trim()) return;\r\n addTodo(input.value);\r\n input.value = \"\";\r\n }}\r\n >\r\n Add Todo\r\n <\/button>\r\n <\/div>\r\n \r\n {(todo) => {\r\n const { id, text } = todo;\r\n console.log(`Creating ${text}`)\r\n return
    \r\n \r\n {text}<\/span>\r\n <\/div>\r\n }}\r\n <\/For>\r\n <\/>\r\n );\r\n};\r\n\r\nrender(App, document.getElementById(\"app\"));" + } + ] +} diff --git a/langs/tr/tutorials/stores_nested_reactivity/lesson.json b/langs/tr/tutorials/stores_nested_reactivity/lesson.json new file mode 100644 index 00000000..32f03a3e --- /dev/null +++ b/langs/tr/tutorials/stores_nested_reactivity/lesson.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { For, createSignal } from \"solid-js\";\n\nconst App = () => {\n const [todos, setTodos] = createSignal([])\n let input;\n let todoId = 0;\n\n const addTodo = (text) => {\n setTodos([...todos(), { id: ++todoId, text, completed: false }]);\n }\n const toggleTodo = (id) => {\n setTodos(todos().map((todo) => (\n todo.id !== id ? todo : { ...todo, completed: !todo.completed }\n )));\n }\n\n return (\n <>\n
    \n \n {\n if (!input.value.trim()) return;\n addTodo(input.value);\n input.value = \"\";\n }}\n >\n Add Todo\n \n
    \n \n {(todo) => {\n const { id, text } = todo;\n console.log(`Creating ${text}`)\n return
    \n \n {text}\n
    \n }}\n
    \n \n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/stores_nested_reactivity/lesson.md b/langs/tr/tutorials/stores_nested_reactivity/lesson.md new file mode 100644 index 00000000..8a3a54c6 --- /dev/null +++ b/langs/tr/tutorials/stores_nested_reactivity/lesson.md @@ -0,0 +1,32 @@ +One of the reasons for fine-grained reactivity in Solid is that it can handle nested updates independently. You can have a list of users and when we update one name we only update a single location in the DOM without diffing the list itself. Very few (even reactive) UI frameworks can do this. + +But how do we accomplish this? In the example we have a list of todos in a signal. In order to mark a todo as complete, we would need to replace the todo with a clone. This is how most frameworks work, but it's wasteful as we rerun the list diffing and we recreate the DOM elements as illustrated in the `console.log`. + +```js +const toggleTodo = (id) => { + setTodos( + todos().map((todo) => (todo.id !== id ? todo : { ...todo, completed: !todo.completed })), + ); +}; +``` + +Instead, in a fine-grained library like Solid, we initialize the data with nested Signals like this: + +```js +const addTodo = (text) => { + const [completed, setCompleted] = createSignal(false); + setTodos([...todos(), { id: ++todoId, text, completed, setCompleted }]); +}; +``` + +Now we can update the completion state by calling `setCompleted` without any additional diffing. This is because we've moved the complexity to the data rather than the view. And we know exactly how the data changes. + +```js +const toggleTodo = (id) => { + const todo = todos().find((t) => t.id === id); + if (todo) todo.setCompleted(!todo.completed()) +} +``` +If you change the remaining references of `todo.completed` to `todo.completed()`, the example should now only run the `console.log` on creation and not when you toggle a todo. + +This of course requires some manual mapping and it was the only choice available to us in the past. But now, thanks to proxies, we can do most of this work in the background without manual intervention. Continue to the next tutorials to see how. diff --git a/langs/tr/tutorials/stores_nested_reactivity/solved.json b/langs/tr/tutorials/stores_nested_reactivity/solved.json new file mode 100644 index 00000000..40223ce6 --- /dev/null +++ b/langs/tr/tutorials/stores_nested_reactivity/solved.json @@ -0,0 +1,8 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport { For, createSignal } from \"solid-js\";\n\nconst App = () => {\n const [todos, setTodos] = createSignal([])\n let input;\n let todoId = 0;\n\n const addTodo = (text) => {\n const [completed, setCompleted] = createSignal(false); \n setTodos([...todos(), { id: ++todoId, text, completed, setCompleted }]);\n }\n const toggleTodo = (id) => {\n const todo = todos().find((t) => t.id === id);\n if (todo) todo.setCompleted(!todo.completed())\n }\n\n return (\n <>\n
    \n \n {\n if (!input.value.trim()) return;\n addTodo(input.value);\n input.value = \"\";\n }}\n >\n Add Todo\n \n
    \n \n {(todo) => {\n const { id, text } = todo;\n console.log(`Creating ${text}`)\n return
    \n \n {text}\n
    \n }}\n
    \n \n );\n};\n\nrender(App, document.getElementById(\"app\"));\n" + } + ] +} diff --git a/langs/tr/tutorials/stores_nocontext/lesson.json b/langs/tr/tutorials/stores_nocontext/lesson.json new file mode 100644 index 00000000..eee66efc --- /dev/null +++ b/langs/tr/tutorials/stores_nocontext/lesson.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport counter from \"./counter\"\n\nfunction Counter() {\n return (\n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "counter", + "content": "import { createSignal, createMemo, createRoot } from \"solid-js\";\n\nfunction createCounter() {\n const [count, setCount] = createSignal(0);\n const increment = () => setCount(count() + 1);\n const doubleCount = createMemo(() => count() * 2);\n return { count, doubleCount, increment };\n}\n\nexport default createRoot(createCounter);" + } + ] +} diff --git a/langs/tr/tutorials/stores_nocontext/lesson.md b/langs/tr/tutorials/stores_nocontext/lesson.md new file mode 100644 index 00000000..e2051130 --- /dev/null +++ b/langs/tr/tutorials/stores_nocontext/lesson.md @@ -0,0 +1,31 @@ +Context is a great tool for stores. It handles injection, ties ownership to the reactive graph, automatically manages disposal, and has no render overhead given Solid's fine-grained rendering. + +Sometimes context is overkill, though; an alternative is to use the reactive system directly. For example, we can build a global reactive data store by creating a signal in a global scope, and `export`ing it for other modules to use: + +```js +import { createSignal } from 'solid-js'; + +export default createSignal(0); + +// somewhere else: +import counter from './counter'; +const [count, setCount] = counter; +``` + +Solid's reactivity is a universal concept. It doesn't matter if it is inside or outside components. There is no separate concept for global vs local state. It is all the same thing. + +The only restriction is that all computations (Effects/Memos) need to be created under a reactive root (`createRoot`). Solid's `render` does this automatically. + +In this tutorial `counter.tsx` is such a global store. We can use it by modifying our component in `main.tsx` to: + +```jsx +const { count, doubleCount, increment } = counter; + +return ( + +); +``` + +So when using your own more complicated global stores that contain computations, be sure to create a root. Or better yet, do yourself a favor and just use Context. diff --git a/langs/tr/tutorials/stores_nocontext/solved.json b/langs/tr/tutorials/stores_nocontext/solved.json new file mode 100644 index 00000000..956fda6b --- /dev/null +++ b/langs/tr/tutorials/stores_nocontext/solved.json @@ -0,0 +1,12 @@ +{ + "files": [ + { + "name": "main", + "content": "import { render } from \"solid-js/web\";\nimport counter from \"./counter\"\n\nfunction Counter() {\n const { count, doubleCount, increment } = counter;\n\n return (\n \n );\n}\n\nrender(() => , document.getElementById(\"app\"));\n" + }, + { + "name": "counter", + "content": "import { createSignal, createMemo, createRoot } from \"solid-js\";\n\nfunction createCounter() {\n const [count, setCount] = createSignal(0);\n const increment = () => setCount(count() + 1);\n const doubleCount = createMemo(() => count() * 2);\n return { count, doubleCount, increment };\n}\n\nexport default createRoot(createCounter);" + } + ] +} From 7813c1cb6a137d83f0b9c5bcbb4ddc442a02c351 Mon Sep 17 00:00:00 2001 From: Wralith Date: Mon, 17 Oct 2022 17:48:33 +0300 Subject: [PATCH 02/17] docs(tr): translate tutorials/introduction_basics --- .../tutorials/introduction_basics/lesson.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/langs/tr/tutorials/introduction_basics/lesson.md b/langs/tr/tutorials/introduction_basics/lesson.md index ead15151..39783bd4 100644 --- a/langs/tr/tutorials/introduction_basics/lesson.md +++ b/langs/tr/tutorials/introduction_basics/lesson.md @@ -1,29 +1,29 @@ -# Introduction +# Giriş -This interactive guide will walk you through Solid's main features. You can also refer to the API and guides to learn more about how Solid works. +Bu interaktif rehber Solid'in ana özelliklerini anlamanızda size yol gösterecektir. Solid'in nasıl çalıştığı hakkında daha fazla bilgi edinmek için API ve rehberlere da başvurabilirsiniz. -You can also check out our new beginner tutorial (work-in-progress!) [here](https://docs.solidjs.com/tutorials/getting-started-with-solid/). +Ayrıca yeni başlangıç rehberimize de [buradan](https://docs.solidjs.com/tutorials/getting-started-with-solid/) göz atabilirsiniz.(hazırlık aşamasında!) -# What is Solid? +# Solid Nedir -Solid is a JavaScript framework for making interactive web applications. -With Solid, you can use your existing HTML and JavaScript knowledge to build components that can be reused throughout your app. -Solid provides the tools to enhance your components with _reactivity_: declarative JavaScript code that links the user interface with the data that it uses and creates. +Solid interaktif web uygulamaları üretmeye yönelik bir Javascript framework'üdür. +Solid ile mevcut HTML ve Javascript bilginizi kullanarak uygulamalarınızda yeniden kullanılabilir bileşenler (component) üretebilirsiniz. +Solid, bileşenleri _reaktivite_ özelliklerine sahip bir şekilde geliştirmek için araçlar sunar: bu sayede deklaratif Javascript kodu ile, kullanıcı arayüzü ve kullanıcı arayüzünü oluşturan, kullanan verinin birlikte çalışmasını sağlar. -# Anatomy of a Solid App +# Solid Uygulamasının Anatomisi -A Solid App is composed of functions that we call components. Take a look at the `HelloWorld` function on the right: it directly returns a `div`! This mix of HTML and JavaScript is called JSX. Solid ships with a compiler that turns these tags into DOM nodes later on. +Solid uygulaması bileşen (component) olarak adlandırdığımız fonksiyonlardan oluşur. Sağdaki `HelloWorld` fonksiyonuna baktığımızda doğrudan `dıv` döndüğünü görüyoruz! Bu HTML ve Javascript karışımı JSX olarak adlandırılmaktadır. Solid bu etiketleri daha sonra DOM nodelarına dönüştüren bir derleyici içermektedir. -JSX allows you to use most HTML elements in our app, but it also lets you create new elements. Once we've declared our `HelloWorld` function, we can use it as a `` tag throughout our app. +JSX, uygulamanızdaki çoğu HTML elementlerini kullanmanıza izin verir, ancak aynı zamanda yeni ögeler üretmenize de olanak tanır. `HelloWorld` fonksiyonumuzu bir kez oluşturduktan sonra uygulamamızın tamamında `` tag'ı ile kullanabiliriz. -The entry point for any Solid App is the `render` function. It takes 2 arguments, a function wrapping our application code and an existing element in the HTML to mount to: +Solid Uygulamasının giriş noktası `render` fonksiyonudur. Bu fonksiyon 2 argüman alır: birincisi uygulamamızın kodunu saran bir fonksiyon, ikincisi ise HTML de mevcut, uygulamanın bağlanacağı elemandır. ```jsx render(() => , document.getElementById("app")); ``` -# Leveraging this Tutorial +# Rehberden Yararlanmak -Each lesson in the tutorial presents a Solid feature and a scenario to try it out. At any point you can click the solve button to see the solution or click reset to start over. The code editor itself has a console and an output tab where you can see the compiled output generated from your code. Look at it if you are curious to see how Solid generates code. +Eğitimdeki her bir ders bir Solid özelliğine eş düşmektedir ve bunu denemek için sizlere bir senaryo sunmaktadır. Herhangi bir noktada çözümü görmek için Çöz düğmesine tıklayabilir veya baştan başlamak için sıfırla düğmesine tıklayabilirsiniz. Kod düzenleyicisinin kendisinde bir konsol ve kodunuzdan oluşturulan derlenmiş çıktıyı görebileceğiniz bir output sekmesi vardır. Solid'in nasıl kod ürettiğini merak ediyorsanız bakabilirsiniz. -Have fun! +İyi eğlenceler! \ No newline at end of file From f0356b96cfff2b8fcce07ffe9dee3cf28f2ac871 Mon Sep 17 00:00:00 2001 From: Wralith Date: Mon, 17 Oct 2022 18:22:57 +0300 Subject: [PATCH 03/17] docs(tr): translate tutorials/introduction_jsx --- langs/tr/tutorials/introduction_jsx/lesson.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/langs/tr/tutorials/introduction_jsx/lesson.md b/langs/tr/tutorials/introduction_jsx/lesson.md index 5e8afc17..c1f30b06 100644 --- a/langs/tr/tutorials/introduction_jsx/lesson.md +++ b/langs/tr/tutorials/introduction_jsx/lesson.md @@ -1,12 +1,12 @@ -JSX is the HTML-like syntax we've seen inside these examples and is core to building components in Solid. -JSX adds dynamic expressions that allow you to reference variables and functions within your HTML by using the `{ } ` syntax. -In this example, we include the string `name` in our HTML using `{name}` inside a div. In the same way, we include an HTML element that was directly assigned to the `svg` variable. +JSX örneklerde gördüğümüz üzere HTML benzeri bir syntax'a sahiptir ve Solid ile bileşen oluşturmanın temelini oluşturmaktadır. +JSX `{ } ` syntax'ını kullanarak HTML üzerinde değişken ve fonksiyonları kullanabilmemize olanak sağlayan dinamik yapılar sunar. +Bu örnekte, `name` değişkenini HTML'de `{name}` şeklinde bir div'in içerisinde kullandık. Aynı şekilde, bir HTML elemanını doğrudan `svg` değişkenine atanacak şekilde ürettik. -Unlike some other frameworks that use JSX, Solid attempts to stay as close to HTML standards as possible, allowing copy and paste from answers on Stack Overflow or from template builders from your designers. +JSX kullanan diğer frameworklerin aksine Solid, HTML standartlarına mümkün olduğunca yakın kalmaya çalışır dolayısıyla Stack Overflow'daki yanıtlardan veya tasarımcıların şablon oluşturucularından kopyalayıp yapıştırma konusunda kolaylık sağlar. -There are 3 main differences between JSX and HTML that prevent JSX from being seen as a superset of HTML: -1. JSX does not have void elements. This means that all elements must have a closing tag or self-close. Keep this in mind when copying over elements like `` or `
    `. -2. JSX must return a single Element. To represent multiple top level elements, use a Fragment element: +JSX'in HTML'i kapsayan bir superset olarak tanımlanmasını engelleyen üç ana farklılık vardır: +1. JSX'te void elemanlar yoktur. Tüm elemanların kapanış etiketine sahip olması veya kendini kapatması gerekir. Bunu `` veya `
    ` gibi yapılar kullanırken göz önünde bulundurmalısınız. +2. JSX sadece bir eleman dönmelidir. Birden çok üst seviye elemana sahip bir yapı istendiği takdirde Fragment elemanı kullanılır. ```jsx <> @@ -14,9 +14,9 @@ There are 3 main differences between JSX and HTML that prevent JSX from being se

    Some Text

    ``` -3. JSX doesn't support HTML Comments `` or special tags like ``. +3. JSX HTML yorumlarını `` veya özel etiketleri `` desteklemez. -But JSX does support SVG. Let's try copying some SVG right into our component: +Fakat JSX, SVG desteklemektedir. Hadi bileşenimize doğrudan bir SVG yapıştıralım: ```jsx From f091c989ae1f8cf026d3ccb5df64f1261cd3e6d1 Mon Sep 17 00:00:00 2001 From: Wralith Date: Mon, 17 Oct 2022 21:34:28 +0300 Subject: [PATCH 04/17] docs(tr): translate tutorials/introduction_components --- langs/tr/tutorials/introduction_components/lesson.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/langs/tr/tutorials/introduction_components/lesson.md b/langs/tr/tutorials/introduction_components/lesson.md index 03568b74..bdf3213c 100644 --- a/langs/tr/tutorials/introduction_components/lesson.md +++ b/langs/tr/tutorials/introduction_components/lesson.md @@ -1,14 +1,14 @@ -As you build your applications, you will want to break apart your code for better modularity and reusability. In Solid, the main way of doing that is by creating components. +Uygulamalarınızı oluştururken kodunuzu parçalara bölmek isteyebilirsiniz, bu tekrar kullanılabilirlik ve modülerlik konularında yararlı olacaktır. Solid'te bunu yapmanın ana yolu bileşen (component) oluşturmaktır. -Components are just functions like the `HelloWorld()` one we've been using so far. What makes them special is that they typically return JSX and can be called by JSX in other components. +Bileşenler temelde `HelloWorld()` - şimdiye kadar kullanmakta olduğumuz - gibi birer fonksiyondur. Bileşenleri özel yapan şey, genellikle JSX döndürmeleri ve diğer bileşenlerde JSX tarafından çağırılabilmeleridir. -In this example, let's add our `Nested` component to our app. We've defined it in another file, though you can put multiple components in the same file. First we must import it: +Hadi örneğimizde `Nested` bileşenimizi uygulamamıza ekleyelim. Bileşeni başka bir dosyada tanımladık, ancak aynı dosyada birden fazla bileşen de barınabilir. Öncelikle aşağıdaki kodu ekleyelim. ```js import Nested from "./nested"; ``` -Then we need to add the component to our JSX. Like before, we now have multiple elements we want to return, so we wrap them in a Fragment: +Sonra bileşenimizi JSX'e ekleyelim. Daha önce bahsedildiği gibi, döndürmek istediğimiz birden fazla elemanımız var, dolayısıyla bu elemanları Fragment ile sarmalıyız. ```jsx function App() { @@ -21,4 +21,4 @@ function App() { } ``` -When the parent component first renders, it will execute the `Nested()` function and won't call it ever again. All updates are applied by Solid’s reactivity system which we will cover in the next couple of lessons. +Ana bileşen ilk kez oluştuğunda `Nested()` fonksiyonunu çalıştıracaktır ve bir daha asla çağırmayacaktır. Sonrasındaki tüm değişiklikler Solid'in önümüzdeki derslerde göreceğimiz reaktivite sistemi tarafından gerçekleştirilecektir. \ No newline at end of file From d33527b83f6f3ed89e0b41284bf86bf204ccb906 Mon Sep 17 00:00:00 2001 From: Wralith Date: Mon, 17 Oct 2022 22:18:47 +0300 Subject: [PATCH 05/17] docs(tr): translate tutorials/introduction_signals --- .../tr/tutorials/introduction_signals/lesson.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/langs/tr/tutorials/introduction_signals/lesson.md b/langs/tr/tutorials/introduction_signals/lesson.md index 465ba9db..e76ff2df 100644 --- a/langs/tr/tutorials/introduction_signals/lesson.md +++ b/langs/tr/tutorials/introduction_signals/lesson.md @@ -1,28 +1,28 @@ -_Signals_ are the cornerstone of reactivity in Solid. They contain values that change over time; when you change a signal's value, it automatically updates anything that uses it. +_Sinyaller_ Solid'te reaktivitenin ana unsurudur. Zaman içinde değişen/değişebilen değerlerden oluşurlar; bir sinyalin değeri değiştiğinde, otomatik olarak o sinyali kullanan diğer her şey de güncellenecektir. -To create a signal, let's import `createSignal` from `solid-js` and call it from our Counter component like this: +Sinyal oluşturmak için `createSignal` fonksiyonunu `solid-js`'den import edelim ve Counter bileşenimizde aşağıdaki gibi çağıralım: ```jsx const [count, setCount] = createSignal(0); ``` -The argument passed to the create call is the initial value, and the return value is an array with two functions, a getter and a setter. By [destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment), we can name these functions whatever we like. In this case, we name the getter `count` and the setter `setCount`. +Create fonksiyonu bir argüman almaktadır ki bu da başlangıç değeridir, sonrasında getter ve setter olmak üzere iki fonksiyondan oluşan bir array döndürür. [destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) ile bu fonksiyonları dilediğimiz gibi isimlendirebiliriz. Bizim durumumuzda getter'i `count` setter'i ise `setCount` olarak isimlendirelim. -It is important to notice that the first returned value is a getter (a function returning the current value) and not the value itself. This is because the framework needs to keep track of where that signal is read so it can update things accordingly. +İlk döndürülen değerin bir getter (mevcut değeri döndüren bir fonksiyon) olduğunu, yani değerin kendisi olmadığına dikkat ediniz. Bunun sebebi framework'ün bu sinyalin nereden okunduğunu takip edebilmesi ve buna göre de güncellemeleri kontrol etmesidir. -In this lesson, we'll use JavaScript's `setInterval` function to create a periodically incrementing counter. We can update our `count` signal every second by adding this code to our Counter component: +Bu derste Javascript'in `setInterval` fonksiyonu ile periyodik olarak artan bir sayaç oluşturacağız. Aşağıdaki kodu Counter bileşenimize ekleyerek `count` sinyalimizi saniyede bir güncelleyebiliriz. ```jsx setInterval(() => setCount(count() + 1), 1000); ``` -Each tick, we read the previous count, add 1, and set the new value. +Her tikte count'un bir önceki değerini okuyup, 1 ekleyip, yeni değer olarak atıyoruz. -> Solid's signals also accept a function form where you can use the previous value to set the next value. +> Solid'de sinyaller parametre olarak fonksiyon da kabul etmektedirler, dolayısıyla bir önceki değeri, yeni değer atamak için kullanabiliriz. > ```jsx > setCount(c => c + 1); > ``` -Finally, we need to read the signal in our JSX code: +Son olarak sinyali JSX içerisinde okumamız gerekiyor: ```jsx return
    Count: {count()}
    ; From 7f6faadd595989f4302028cfdcfa2b83b351aef0 Mon Sep 17 00:00:00 2001 From: Wralith Date: Mon, 17 Oct 2022 23:51:25 +0300 Subject: [PATCH 06/17] docs(tr): translate tutorials/introduction_effects --- langs/tr/tutorials/introduction_effects/lesson.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/langs/tr/tutorials/introduction_effects/lesson.md b/langs/tr/tutorials/introduction_effects/lesson.md index e422d495..b6a11ade 100644 --- a/langs/tr/tutorials/introduction_effects/lesson.md +++ b/langs/tr/tutorials/introduction_effects/lesson.md @@ -1,8 +1,8 @@ -Signals are trackable values, but they are only one half of the equation. To complement those are observers that can be updated by those trackable values. An _effect_ is one such observer; it runs a side effect that depends on signals. +Sinyaller takip edilebilir değerlerdir, ancak bu denklemin sadece yarısıdır. Tamamlanması için bu izlenebilir değerler tarafından güncellenebilen gözlemciler kullanılır. Effect bir gözlemcidir ve işlevi sinyale bağlı bir side-effect çalıştırmaktır. -An effect can be created by importing `createEffect` from `solid-js` and providing it a function. The effect automatically subscribes to any signal that is read during the function's execution and reruns when any of them change. +Effect oluşturmak için `solid-js`'ten `createEffect`'i import ediyoruz ve içerisinde bir fonksiyon oluşturuyoruz. Effect otomatik olarak fonksiyon çalışırken okunan sinyallere subscribe olur ve bunlardan birisi değiştiğinde fonksiyonu yeniden çalıştırır. -So let's create an Effect that reruns whenever `count` changes: +Hadi `count` her değiştiğine çalışan bir Effect oluşturalım. ```jsx createEffect(() => { @@ -10,12 +10,12 @@ createEffect(() => { }); ``` -To update our `count` Signal, we'll attach a click handler on our button: +`count` sinyalimizi güncellemek için bir butona tıklandığında çalışacak bir fonksiyon atayalım. ```jsx ``` -Now clicking the button writes to the console. This is a relatively simple example, but to understand how Solid works, you should imagine that every expression in JSX is its own effect that re-executes whenever its dependent signals change. This is how all rendering works in Solid: from Solid's perspective, *all rendering is just a side effect of the reactive system*. +Artık her butona tıklandığında konsol'a yazıyor. Bu örnek görece basit bir örnek, fakat Solid'in nasıl çalıştığını anlamak için, JXT içindeki her ifadenin bağımlı sinyalleri değiştiğinde yeniden çalıştırılan kendine ait bir effect olduğunu hayal etmelisiniz. Solid içerisindeki bütün render işlemleri bu şekilde çalışır, Solid perspektifinde: *bütün render işlemleri reaktif sistemin bir side effect'idir*. -> Effects that developers create with `createEffect` run after rendering has completed and are mostly used for scheduling updates that interact with the DOM. If you want to modify the DOM earlier, use [`createRenderEffect`](https://www.solidjs.com/docs/latest/api#createrendereffect). \ No newline at end of file +> Geliştiricinin `createEffect` ile oluşturduğu effectler render işlemi tamamlandıktan sonra çalışır ve çoğunlukla DOM ile etkileşime giren güncellemeleri zamanlamak için kullanılırlar. DOM'u öncesinde değiştirmek istiyorsanız [`createRenderEffect`](https://www.solidjs.com/docs/latest/api#createrendereffect) kullanabilirsiniz. \ No newline at end of file From baa5ea75da585d468b502123c685d54f1f38cf19 Mon Sep 17 00:00:00 2001 From: Wralith Date: Tue, 18 Oct 2022 00:06:28 +0300 Subject: [PATCH 07/17] docs(tr): translate tutorials/introduction_derived --- langs/tr/tutorials/introduction_derived/lesson.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/langs/tr/tutorials/introduction_derived/lesson.md b/langs/tr/tutorials/introduction_derived/lesson.md index 38650c11..7d212ff0 100644 --- a/langs/tr/tutorials/introduction_derived/lesson.md +++ b/langs/tr/tutorials/introduction_derived/lesson.md @@ -1,16 +1,16 @@ -We've seen that whenever we access a signal in JSX, it will automatically update the view when that signal changes. But the component function itself only executes once. +JSX ile bir sinyale her erişildiğinde, görünümün de bu sinyale bağlı olarak otomatik olarak güncellendiğini gördük. Ancak, bileşen fonksiyonunun kendisi sadece bir kez çalışmaktadır. -We can create new expressions that depend on signals by wrapping a signal in a function. A function that accesses a signal is effectively also a signal: when its wrapped signal changes it will in turn update its readers. +Bir sinyali başka bir fonksiyon ile sararak sinyale bağlı yeni ifadeler oluşturulabilir. Bu sinyale erişen fonksiyonun kendisi de aynı zamanda bir sinyaldir: sardığı sinyal değiştiğinde fonksiyona erişmekte olan okuyucular da güncellenecektir. -Let's update our Counter to count by 2 by introducing a `doubleCount` function: +Counter'ı, artık ikişer ikişer saymak üzere, `doubleCount` fonksiyonu ile güncelleyelim: ```jsx const doubleCount = () => count() * 2; ``` -We can then call `doubleCount` just like a signal in our JSX: +Sonrasında `doubleCount` fonksiyonunu, bir sinyali nasıl çağırıyorsak aynı şekilde JSX üzerinde çağırabiliriz: ```jsx return
    Count: {doubleCount()}
    ; ``` -We call functions like these _derived signals_ because they gain their reactivity from the signal they access. They don't themselves store a value (if you create a derived signal but never call it, it will be stripped from Solid's output like any unused function) but they'll update any effects that depend on them, and they'll trigger a rerender if included in a view. \ No newline at end of file +Bu tür fonksiyonlara _derived signal_ (türetilmiş sinyal) diyoruz çünkü reaktiviteleri eriştikleri sinyalden gelmekte. Kendileri bir değer saklamazlar, (bir derived signal oluşturur ve onu hiç çağırmazsanız, kullanılmayan herhangi bir fonksiyon gibi Solid'in çıktısından çıkarılacaktır) ancak kendilerine bağlı olan tüm efektleri güncellerler ve bir görünüme dahil edildiklerinde re-render'ı tetiklerler. \ No newline at end of file From 6043c23b25726f74c6a15eaafe5ea03d269026be Mon Sep 17 00:00:00 2001 From: Wralith Date: Tue, 18 Oct 2022 00:31:40 +0300 Subject: [PATCH 08/17] docs(tr): translate tutorials/introduction_memos --- langs/tr/tutorials/introduction_memos/lesson.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/langs/tr/tutorials/introduction_memos/lesson.md b/langs/tr/tutorials/introduction_memos/lesson.md index ec135072..6f645b6d 100644 --- a/langs/tr/tutorials/introduction_memos/lesson.md +++ b/langs/tr/tutorials/introduction_memos/lesson.md @@ -1,13 +1,13 @@ -Most of the time, composing derived signals is sufficient. However, it is sometimes beneficial to cache values in order to reduce duplicated work. We can use memos to evaluate a function and store the result until its dependencies change. This is great for caching calculations for effects that have other dependencies and mitigating the work required for expensive operations like DOM node creation. +Genellikle, türetilmiş sinyaller (derived signal) oluşturmak yeterli olsa bile, bazen tekrarlanan işleri azaltmak için değerleri önbelleğe almak faydalı olabilir. Bir fonksiyonu değerlendirmek ve bağımlılıkları değişene kadar sonucu saklamak için memo'lar kullanılabilir. Bu sayede, başka bağımlılıklara sahip efektler için hesaplamaları önbelleğe almak veya DOM node'u oluşturmak gibi maliyetli işlemlerde, yükü azaltmak için yerinde bir çözüme ulaşılabilir. -Memos are both an observer, like an effect, and a read-only signal. Since they are aware of both their dependencies and their observers, they can ensure that they run only once for any change. This makes them preferable to registering effects that write to signals. Generally, what can be derived, should be derived. +Memo'lar hem gözlemci - bir effect gibi -, hem de salt okunur bir sinyaldir. Hem bağımlılıkların hem de gözlemcilerinin farkındadırlar ve bu sayede herhangi bir değişiklik için yalnızca bir kez çalıştırılması sağlanır. Bu durum da onları sinyalleri değiştiren efektleri kaydederken tercih edilebilir kılar. Genel olarak, bir şey türetilebiliyorsa, türetilmelidir. -Creating a Memo is as simple as passing a function to `createMemo`, imported from `solid-js`. In the example, recalculating the value gets increasingly more expensive with each click. If we wrap it in `createMemo`, it recalculates only once per click: +Memo `solid-js`'ten import edeceğimiz `createMemo`'ya fonksiyonu aktararak basit bir şekilde oluşturulabilir. Örnekte, sonucu tekrar hesaplamak her tıklamada daha maliyetli hale gelmekte. Fakat fonksiyonu `createMemo` ile sardığımızda her tıklamada gerekli hesaplama sadece bir kere gerçekleşecektir: ```jsx const fib = createMemo(() => fibonacci(count())); ``` -Place a `console.log` inside the `fib` function to confirm how often it runs: +`fib` fonksiyonunun içerisine `console.log` koyarak ne sıklıkla çalıştığını gözlemleyebiliriz: ```jsx const fib = createMemo(() => { console.log("Calculating Fibonacci"); From 36a6ca9edc5c76f3a5f70a5c315fc9979457cc4e Mon Sep 17 00:00:00 2001 From: Wralith Date: Tue, 18 Oct 2022 16:57:28 +0300 Subject: [PATCH 09/17] docs(tr): translate tutorials/flow --- langs/tr/tutorials/flow_dynamic/lesson.md | 8 ++++---- langs/tr/tutorials/flow_error_boundary/lesson.md | 4 ++-- langs/tr/tutorials/flow_for/lesson.md | 10 +++++----- langs/tr/tutorials/flow_index/lesson.md | 12 ++++++------ langs/tr/tutorials/flow_portal/lesson.md | 6 +++--- langs/tr/tutorials/flow_show/lesson.md | 10 +++++----- langs/tr/tutorials/flow_switch/lesson.md | 6 +++--- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/langs/tr/tutorials/flow_dynamic/lesson.md b/langs/tr/tutorials/flow_dynamic/lesson.md index 7a09c912..5cbf555a 100644 --- a/langs/tr/tutorials/flow_dynamic/lesson.md +++ b/langs/tr/tutorials/flow_dynamic/lesson.md @@ -1,8 +1,8 @@ -The `` tag is useful when you render from data. It lets you pass either a string for a native element or a component function and it will render that with the rest of the provided props. +`` etiketi verilerden render yapacağınız durumlarda kullanışlıdır. İçerisine native elemanlar için string veya bileşen fonksiyonu iletilebilir ve sonuçta sağlanan diğer prop'lar ile beraber ilettiğiniz eleman render edilir. -This is often more compact than writing a number of `` or `` components. +`` bileşeni genellikle ard arda yazılmış `` veya `` ile karşılaştırıldığında daha kısa ve etkili bir kullanım sağlar. -In the example, we can replace the `` statement: +Örneğimizdeki `` ifadesini: ```jsx }> @@ -11,7 +11,7 @@ In the example, we can replace the `` statement: ``` -with: +aşağıdaki kullanım ile değiştirebiliriz: ```jsx diff --git a/langs/tr/tutorials/flow_error_boundary/lesson.md b/langs/tr/tutorials/flow_error_boundary/lesson.md index 60279577..84ee9a1e 100644 --- a/langs/tr/tutorials/flow_error_boundary/lesson.md +++ b/langs/tr/tutorials/flow_error_boundary/lesson.md @@ -1,6 +1,6 @@ -A JavaScript error originating in the UI shouldn’t break the whole app. Error boundaries are components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. +UI kaynaklı bir JavaScript hatasının tüm uygulamayı bozmaması gerekir. Error boundaries (Hata sınırları), child bileşen ağacındaki bir JavaScript hatasını yakalayan, loglayan ve sonrasında hata alınan bileşen ağacı yerine fallback UI'ı görüntüleyen bileşenlerdir. -A component has crashed our example. Let's wrap it in an Error Boundary that displays the error. +Örneğimizde hata sonucu çöken bir bileşen var, bileşeni hatayı gösterecek şekilde Error Boundary ile saralım. ```jsx err}> diff --git a/langs/tr/tutorials/flow_for/lesson.md b/langs/tr/tutorials/flow_for/lesson.md index b930b0ea..2759d2be 100644 --- a/langs/tr/tutorials/flow_for/lesson.md +++ b/langs/tr/tutorials/flow_for/lesson.md @@ -1,4 +1,4 @@ -The `` component is the best way to loop over an array of objects. As the array changes, `` updates or moves items in the DOM rather than recreating them. Let's look at an example. +`` bileşeni objelerden oluşan bir array üzerinde döngü oluşturmanın en iyi yoludur. Array değiştiği takdirde `` ögelerin yeniden oluşturulması yerine DOM üzerinde güncellenmesi veya taşınmasını sağlar. Gelin örneğe bir bakalım. ```jsx {(cat, i) => @@ -10,10 +10,10 @@ The `` component is the best way to loop over an array of objects. As the a } ``` -There is one prop on the `` component: `each`, where you pass the array to loop over. +`` bileşeni için sadece bir prop vardır: `each`. Döngü oluşturacağınız array `each`'a aktarılır. -Then, instead of writing nodes directly between `` and ``, you pass a _callback_. This is a function similar to JavaScript's [`map` callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#parameters). For each element in the array, the callback is called with the element as the first argument and the index as the second. (`cat` and `i` in this example.) You can then make use of those in the callback, which should return a node to be rendered. +Sonrasında, `` ve `` arasına doğrudan node'ları yazmak yerine _callback_ fonksiyonu aktarılır. Bu fonksiyon JavaScript'in [`map` callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#parameters) fonksiyonuna benzemektedir. Array'deki her eleman için, eleman ilk argüman olarak ve index ikinci argüman olarak geri çağrılır. (Bu örnekte `cat` ve `i`.) Daha sonra, işlenecek bir node döndürmesi gereken callback'te bu değerleri kullanabilirsiniz. -Note that the index is a _signal_, not a constant number. This is because `` is "keyed by reference": each node that it renders is coupled to an element in the array. In other words, if an element changes placement in the array, rather than being destroyed and recreated, the corresponding node will move too and its index will change. +Dikkat edilmesi gereken bir diğer konu da index'in sabit bir sayı değil bir _sinyal_ oluşudur. Bunun nedeni `` un referansla anahtarlanmış (keyed by reference) olmasıdır: işlenilen her bir node array'deki bir elemana bağlıdır. Başka bir deyişle, bir ögenin array'deki yeri değiştirildiğinde yok edilip yeniden oluşturulmak yerine, ilgili node da hareket edecek ve index'i değiştirecektir. -The `each` prop expects an array, but you can turn other iterable objects into arrays with utilities like [`Array.from`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from), [`Object.keys`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys), or [`spread syntax`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax). +`each` prop'u bir array beklemektedir ancak [`Array.from`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from), [`Object.keys`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys), veya [`spread syntax`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) gibi yardımcılarla diğer yinelenebilir nesneleri array'lere dönüştürebilirsiniz. \ No newline at end of file diff --git a/langs/tr/tutorials/flow_index/lesson.md b/langs/tr/tutorials/flow_index/lesson.md index 5c00894f..f2594b00 100644 --- a/langs/tr/tutorials/flow_index/lesson.md +++ b/langs/tr/tutorials/flow_index/lesson.md @@ -1,10 +1,10 @@ -You now know how to render lists in Solid with ``, but Solid also provides the `` component, which will cause less rerenders in certain situations. +Artık Solid'de `` ile bir listeyi nasıl oluşturacağınızı biliyorsunuz, ancak Solid belirli durumlarda daha az re-render üretecek `` bileşeni de sağlamaktadır. -When the array updates, the `` component uses referential equality to compare elements to the last state of the array. But this isn't always desired. +Array güncellendiğinde `` bileşeni elemanları array'in son durumu ile karşılaştırmak için referans eşitliğini kullanır fakat bu her zaman arzulanan bir durum olmayabilir. -In JavaScript, primitives (like strings and numbers) are always compared by value. When using `` with primitive values or arrays of arrays, we could cause a lot of unnecessary rendering. If we used `` to map a list of strings to `` fields that could edit each, every change to that value would cause the `` to be recreated. +JavaScript'te primitifler (string veya number gibi) her zaman değerlerine göre karşılaştırılır. `` bileşenini primitif değerlerle veya array'lerden oluşan array'ler ile kullanmak gereksiz render'lara sebep olabilir. Örneğin, bir string listesini her biri düzenlenebilen `` alanlarına eşlemek için `` kullansaydık, bu değerdeki her değişiklik ``'un yeniden oluşturulmasına neden olurdu. -The `` component is provided for these cases. As a rule of thumb, when working with primitives use ``. +Bu durumlar için `` bileşeni sağlanmıştır. Genel bir kural olarak, primitif ögelerle çalışırken `` bileşenini kullanın. ```jsx {(cat, i) => @@ -16,6 +16,6 @@ The `` component is provided for these cases. As a rule of thumb, when wo } ``` - It has a similar signature to ``, except this time the item is the signal and the index is fixed. Each rendered node corresponds to a spot in the array. Whenever the data in that spot changes, the signal will update. +``, `` ile benzer bir imzaya sahiptir, ancak bu kez öge sinyaldir ve index sabittir. Oluşturulan her node array'deki bir noktaya karşılık gelir ve bu noktadaki veri her değiştiğinde, sinyal güncellenir. -`` cares about each piece of data in your array, and the position of that data can change; `` cares about each index in your array, and the content at each index can change. +`` array'deki her bir veri parçasıyla ilgilenir ve bu verilerin konumu değişebilir; `` ise array'deki her bir index'le ilgilenir ve her index'in içeriği değişebilir. diff --git a/langs/tr/tutorials/flow_portal/lesson.md b/langs/tr/tutorials/flow_portal/lesson.md index 81b99ecf..45390ee0 100644 --- a/langs/tr/tutorials/flow_portal/lesson.md +++ b/langs/tr/tutorials/flow_portal/lesson.md @@ -1,8 +1,8 @@ -Sometimes it's beneficial to insert elements outside the normal flow of the app. Z-indexes are sometimes insufficient to deal with render contexts for floating elements like Modals. +Bazen ögeleri uygulamanın normal akışının dışına çıkarmak faydalı olabilir. Z-indeksleri de bazen modal'lar gibi floating (kayan) ögelerin render bağlamları ile uyumunda yetersiz kalabilir. -Solid has a `` component whose child content will be inserted at the location of your choosing. By default, its elements will be rendered in a `
    ` in the `document.body`. +Solid bu probleme cevap olarak `` bileşenini sunar, işlevi child (alt, içerdiği, sardığı) içeriğini belirlenen konuma eklemektir. Varsayılan olarak sardığı ögeler `document.body` içerisinde bir `
    ` içinde render edilir. -In the example, we see our information popup get cut off. We can solve this by pulling it out of the flow by wrapping the element in a ``: +Örneğimizde, bilgi popup'ının kesildiğini görüyoruz. Bu sorunu, ögeyi bir `` içerisine alarak, dolayısıyla akıştan çıkararak çözebiliriz. ```jsx diff --git a/langs/tr/tutorials/flow_show/lesson.md b/langs/tr/tutorials/flow_show/lesson.md index 4ee51a95..0347d2a3 100644 --- a/langs/tr/tutorials/flow_show/lesson.md +++ b/langs/tr/tutorials/flow_show/lesson.md @@ -1,8 +1,8 @@ -JSX allows you to use JavaScript to control the logic flow in the templates. However, without a Virtual DOM, naive use of things like `Array.prototype.map` would wastefully recreate all the DOM nodes on every update. Instead it is common for Reactive libraries to use template helpers. In Solid we wrap them in components. +JSX, templatelardaki mantık akışlarını kontrol etmek için JavaScript kullanmanıza olanak sağlar. Ancak, Virtual DOM olmadan `Array.prototype.map` gibi kullanımlar, her güncellemede tüm DOM node'larını gerek olmadığı halde yeniden oluşturacaktır. Bunun yerine Reactive kütüphanelerde template helper'lar kullanılması yaygındır. Solid içerisinde biz bunları bileşenler içerisine sardık. -The most basic control flow is the conditional. Solid's compiler is smart enough to optimally handle ternaries (`a ? b : c`) and boolean expressions (`a && b`). However, often it is more readable to use Solid's `` component. +En temel kontrol akışı (control flow) koşuldur. Solid derleyicisi ternary ifadeleri (`a ? b : c`) ve boolean ifadeleri (`a && b`) optimal şekilde işleyecek kadar akıllıdır, ancak okuma kolaylığı bağlamında Solid'in `` bileşeni genellikle daha kullanışlıdır. -In the example, we would like to show only the appropriate button that reflects the current state (whether the user is logged in). Update the JSX to: +Örnekte, yalnızca mevcut durumu gösteren (kullanıcı girişi yapılıp yapılmadığı) bir buton var. JSX'i aşağıdaki şekilde güncelleyin: ```jsx Log out ``` -The `fallback` prop acts as the `else` and will show when the condition passed to `when` is not truthy. +`fallback` prop'u `else` işlevi görür ve `when`'e ilişkilendirilen koşul truthy olmadığında gösterilir. -Now clicking the button will change back and forth like you would expect. +Artık butona tıklamak beklenildiği gibi iki durum arasında ileri geri geçiş yapmamızı sağlamakta. diff --git a/langs/tr/tutorials/flow_switch/lesson.md b/langs/tr/tutorials/flow_switch/lesson.md index f460fd82..a8aaa333 100644 --- a/langs/tr/tutorials/flow_switch/lesson.md +++ b/langs/tr/tutorials/flow_switch/lesson.md @@ -1,8 +1,8 @@ -Sometimes you need to deal with conditionals with more than 2 mutual exclusive outcomes. For this case, we have the `` and `` components modeled roughly after JavaScript's `switch`/`case`. +Bazen ikiden fazla durumu kapsayan koşullu ifadeler kullanmanız gerekebilir. Bu durum için, kabaca JavaScript'in `switch`/`case` özelliğine karşılık olarak tasarlanan Solid'in `` ve `` bileşenlerini kullanabiliriz. -It will try in order to match each condition, stopping to render the first that evaluates to true. Failing all of them, it will render the the fallback. +Switch, ilk eşleşen koşulu işlemek (render) için sırası ile deneyecek ve eşleşen koşul işlendiğinde duracaktır. Bütün koşullar başarısız olduğu takdirde ise fallback'i işleyecektir. -In the example, we can replace our nested `` components with this: +Örneğimizde, iç içe geçmiş `` bileşenimizi aşağıdaki kullanım ile değiştirebiliriz: ```jsx {x()} is between 5 and 10

    }> From 75a247998b47d140c76e29091ffa6fdad0169dda Mon Sep 17 00:00:00 2001 From: Wralith Date: Tue, 18 Oct 2022 17:38:17 +0300 Subject: [PATCH 10/17] docs(tr): translate tutorials/lifecycles --- langs/tr/tutorials/lifecycles_oncleanup/lesson.md | 6 +++--- langs/tr/tutorials/lifecycles_onmount/lesson.md | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/langs/tr/tutorials/lifecycles_oncleanup/lesson.md b/langs/tr/tutorials/lifecycles_oncleanup/lesson.md index 0fdc6207..2262fefb 100644 --- a/langs/tr/tutorials/lifecycles_oncleanup/lesson.md +++ b/langs/tr/tutorials/lifecycles_oncleanup/lesson.md @@ -1,8 +1,8 @@ -Some frameworks pair their cleanup methods as return values of their side effects or lifecycle methods. Since everything in a Solid render tree is living inside a (possibly inert) Effect and can be nested, we made `onCleanup` a first-class method. You can call it at any scope and it will run when that scope is triggered to re-evaluate and when it is finally disposed. +Bazı frameworkler temizleme (cleanup) metotlarını side-effect'lerin veya lifecycle fonksiyonlarının dönüş değerleri olarak eşleştirir/kullanır. Solid render ağacındaki her şey (muhtemelen atıl/durağan) bir Effect'in içinde yaşadığı ve iç içe geçebildiği için `onCleanup`'ı birinci sınıf bir fonksiyon haline getirdik. `onCleanup` Herhangi bir kapsamda çağrılabilir: bu kapsam yeniden değerlendirilmek (re-evaluate) için tetiklendiğinde ve son olarak kaldırıldığında çalışacaktır. -Use it in your components or in your Effects. Use it in your custom directives. Use it pretty much anywhere that is part of the synchronous execution of the reactive system. +`onCleanup`'ı bileşenlerinizde veya Effect'lerinizde kullanabilirsiniz. Özel tanımladığınız direktiflerde kullanabilirsiniz. Reaktif sistemin senkronize yürütülmesine bağlı olan hemen hemen her yerde kullanabilirsiniz. -The Signal example from the introduction never cleaned up after itself. Let's fix that by replacing the `setInterval` call with this: +Eğitimin giriş bölümündeki sinyal örneği hiçbir zaman kendisini temizlemiyordu, Bu problemi `setInterval` çağrısını aşağıdaki ile değiştirerek düzeltelim: ```js const timer = setInterval(() => setCount(count() + 1), 1000); diff --git a/langs/tr/tutorials/lifecycles_onmount/lesson.md b/langs/tr/tutorials/lifecycles_onmount/lesson.md index c84128b3..c1bd01b1 100644 --- a/langs/tr/tutorials/lifecycles_onmount/lesson.md +++ b/langs/tr/tutorials/lifecycles_onmount/lesson.md @@ -1,11 +1,11 @@ -There are only a few Lifecycle functions in Solid as everything lives and dies by the reactive system. The reactive system is created and updates synchronously, so the only scheduling comes down to Effects which are pushed to the end of the update. +Solid'de az sayıda Lifecycle (Yaşam Döngüsü) fonksiyonu vardır, çünkü her şey reaktif sistem içerisinde yaşar ve son bulur. Reaktif sistem senkronize şekilde oluşur ve güncellenir, bu nedenle de sadece zamanlama (scheduling) güncellemenin sonuna eklenen efektlere gelir. -We've found that developers doing basic tasks don't often think this way, so to make things a -little easier we've made an alias, `onMount`. `onMount` is just a `createEffect` call that is -non-tracking, which means it never re-runs. It is just an Effect call but you can use it with confidence -that it will run only once for your component, once all initial rendering is done. +Temel görevleri yerine getiren geliştiricilerin genellikle bu şekilde düşünmediğini fark ettik ve bu yüzden +işleri kolaylaştırmak için `onMount` adında bir alias oluşturduk. `onMount` aslında, sadece takip edilmeyen (non-tracking) bir `createEffect` +çağrısıdır ve asla tekrar çağrılmaz. +Yani `onMount` initial rendering tamamlandıktan hemen sonra sadece bir kere çalışacağından emin olabileceğiniz bir effect çağrısıdır. -Let's use the `onMount` hook to fetch some photos: +`onMount` hook'unu fetch ile beraber resimleri getirmek için kullanalım: ```js onMount(async () => { const res = await fetch(`https://jsonplaceholder.typicode.com/photos?_limit=20`); @@ -13,4 +13,4 @@ onMount(async () => { }); ``` -Lifecycles are only run in the browser, so putting code in `onMount` has the benefit of not running on the server during SSR. Even though we are doing data fetching in this example, usually we use Solid's resources for true server/browser coordination. +Yaşam döngüleri sadece tarayıcıda çalışır, dolaysıyla `onMount` içerisine kod yazmak SSR sırasında sunucuda çalışmama avantajını sağlar. Bu örnekte veri getirme (fetching) işlemi kullanmış olsak da, genellikle gerçek sunucu/tarayıcı koordinasyonu için Solid'in resource'larını kullanırız. \ No newline at end of file From fdb6d4332e5319084fd1d3d119813a721bc4ea5f Mon Sep 17 00:00:00 2001 From: Wralith Date: Wed, 19 Oct 2022 17:04:07 +0300 Subject: [PATCH 11/17] docs(tr): translate tutorials/bindings --- langs/tr/tutorials/bindings_classlist/lesson.md | 8 ++++---- langs/tr/tutorials/bindings_directives/lesson.md | 12 ++++++------ langs/tr/tutorials/bindings_events/lesson.md | 8 ++++---- langs/tr/tutorials/bindings_forward_refs/lesson.md | 6 +++--- langs/tr/tutorials/bindings_refs/lesson.md | 10 +++++----- langs/tr/tutorials/bindings_spreads/lesson.md | 6 +++--- langs/tr/tutorials/bindings_style/lesson.md | 8 ++++---- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/langs/tr/tutorials/bindings_classlist/lesson.md b/langs/tr/tutorials/bindings_classlist/lesson.md index 0e29c2db..c6c1647f 100644 --- a/langs/tr/tutorials/bindings_classlist/lesson.md +++ b/langs/tr/tutorials/bindings_classlist/lesson.md @@ -1,6 +1,6 @@ -Solid uses `class` to set the `className` property on an element. However it is often convenient to conditionally set classes. For that reason, Solid has a built-in `classList` JSX attribute that takes an object where the key is the class name(s) and the value is a boolean expression. When true, the class is applied, and when false, it is removed. +Solid bir öğe üzerinde `className` property'sini ayarlamak için `class` kelimesini kullanır. Ancak class'lara koşul eklemek istediğiniz durumlar olabilir. Bu nedenle Solid, anahtarların class isimleri ve değerin boolean bir ifade olduğu bir obje alan yerleşik bir `classList` JSX attribute'una sahiptir. Boolean karşılığına göre sınıflar uygulanır veya kaldırılır. -In the example, we can replace: +Örneğimizde aşağıdaki kodu: ```jsx ``` -with: +classList kullanacak şekilde değiştirebiliriz: ```jsx ``` -Remember that you can apply names dynamically like what you'd receive in CSS modules as well: +CSS modules'tan aldığınız sınıfları dinamik olarak da uygulayabileceğinizi unutmayın: ```jsx import { active } from "./style.module.css" diff --git a/langs/tr/tutorials/bindings_directives/lesson.md b/langs/tr/tutorials/bindings_directives/lesson.md index 5b144d3a..7c675644 100644 --- a/langs/tr/tutorials/bindings_directives/lesson.md +++ b/langs/tr/tutorials/bindings_directives/lesson.md @@ -1,10 +1,10 @@ -Solid supports custom directives through the `use:` namespace. This is just a syntactic sugar over `ref`, but is useful in that it resembles typical bindings and there can be multiple bindings on the same element without conflict. This makes it a better tool for reusable DOM element behavior. +Solid özel direktifleri `use:` namespace'i aracılığı ile destekler. Bu aslında sadece `ref` üzerinde bir syntactic sugar'dır ancak tipik binding'lere benzemesi ve aynı eleman üzerinde çakışma olmadan birden fazla binding olabilmesi açısından kullanışlıdır. -A custom directive is a function taking arguments `(element, valueAccesor)`, where `element` is the DOM element with the `use:` attribute, and `valueAccessor` is a getter function for the value assigned to the attribute. As long as the function is imported in scope, you can use it with `use:`. +Özel direktif `(element, valueAccessor)` argümanlarını alan bir fonksiyondur, `element`, `use` attribute'una sahip bir DOM elemanına ve `valueAccessor` da bu attribute'a atanmış değerin getter fonksiyonuna eş düşer. Fonksiyon kapsam (scope) içerisinde aktarıldığı sürece `use:` ile kullanılabilir. -> Important: `use:` is detected by the compiler to be transformed, and the function is required to be in scope, so it cannot be part of spreads or applied to a component. +> Önemli: derleyici `use:`'u dönüştürülmesi gerektiği şeklinde algılar, dolayısıyla fonksiyonun kapsam içerisinde olması gerekir. Bu nedenle spread ile kullanılamaz veya bir bileşene uygulanamaz. -In the example, we are going to make a wrapper for basic click-outside behavior to close a popup or modal. First we need to import and use our `clickOutside` directive on our element: +Örneğimizde, bir popup veya modal'ı dışarı tıklandığında kapanacak şekilde bir wrapper üreteceğiz. Öncelikle `clickOutside` direktifini import etmemiz ve elemanın üzerinde kullanmamız gerekiyor: ```jsx ``` -Open `click-outside.tsx`, where we will be defining our custom directive. This directive defines a click handler that we bind to the body and cleanup when it is time: +Özel direktifimizi tanımlayacağımız `click-outside.tsx` doyasını açalım. Bu direktif, body'e bağlayacağımız ve zamanı geldiğinde temizleyeceğimiz bir click handler tanımlamakta: ```jsx export default function clickOutside(el, accessor) { @@ -23,4 +23,4 @@ export default function clickOutside(el, accessor) { } ``` -Now you should be able to go back and forth between opening and closing the modal. +Artık modal istenildiği şekilde açılıp kapanma özelliklerine sahip. diff --git a/langs/tr/tutorials/bindings_events/lesson.md b/langs/tr/tutorials/bindings_events/lesson.md index 9fea8f2b..f5fdb760 100644 --- a/langs/tr/tutorials/bindings_events/lesson.md +++ b/langs/tr/tutorials/bindings_events/lesson.md @@ -1,6 +1,6 @@ -Events in Solid are attributes prefixed with `on`. They are treated specially in a few ways. First, they do not follow the normal heuristics for wrapping. In many cases, it is difficult to determine the difference between a Signal and an event handler. And so, since events are called and don't require reactivity to update, they are only bound initially. You can always just have your handler run different code based on the current state of your app. +Solid'deki event'ler `on` ön adına sahip niteliklerdir (attribute) ve birkaç yönden özel olarak ele alınırlar. Öncelikle wrapping konusunda normal buluşsallığı (heuristic) takip etmezler; çoğu durumda, bir sinyal ile bir event handler arasındaki farkı saptamak zordur. Bu nedenle, event'ler çağrıldıklarından ve de güncelleme işlemi için reaktivite gerektirmediklerinden yalnızca başlangıçta bağlanırlar. Handler'ın uygulamanın mevcut durumuna göre farklı kod çalıştırması sağlanılabilir. -Common UI events (that bubble and are composed) are automatically delegated to the document. To improve delegated performance, Solid supports an array syntax to call the handler with data (as the first argument) without creating additional closures: +Ortak UI event'leri (bubble oluşturan, oluşturulan) otomatik olarak belgede temsil edilir. Bu bağlamda performansı iyileştirmek için Solid, ek closure'lar oluşturmadan handler'ı verilerle (ilk argüman olarak) çağırmak için bir dizi syntax'ı destekler. ```jsx const handler = (data, event) => /*...*/ @@ -8,14 +8,14 @@ const handler = (data, event) => /*...*/ ``` -In the example, let's attach the handler to the `mousemove` event: +Örneğimizde, handler'ı `mousemove` event'ine bağlayalım: ```jsx
    The mouse position is {pos().x} x {pos().y}
    ``` -All `on` bindings are case insensitive which means that event names need to be in lowercase. For example, `onMouseMove` monitors the event name `mousemove`. If you need to support other casings or not use event delegation, you can use `on:` namespace to match event handlers that follows the colon: +Tüm `on` bind'ları (bağ) büyük/küçük harf farkına duyarlı değildir, bu da event adlarının küçük harfle yazılması gerektiği anlamına gelir. Örneğin: `onMouseMove`, `mousemove` event adını izler. Büyük/küçük harf kullanımını desteklemek veya event temsilini (event delegation) kullanmamak istediğiniz durumlarda `on:` namespace'ini iki noktadan sonra gelecek event handler ile eşleşecek şekilde kullanabilirsiniz: ```jsx diff --git a/langs/tr/tutorials/bindings_forward_refs/lesson.md b/langs/tr/tutorials/bindings_forward_refs/lesson.md index 95a3a203..9e86ac75 100644 --- a/langs/tr/tutorials/bindings_forward_refs/lesson.md +++ b/langs/tr/tutorials/bindings_forward_refs/lesson.md @@ -1,8 +1,8 @@ -On many occassions, you might want to expose a ref from inside a component to a parent. The way we do this is still by using the `ref` attribute. From the outside, using `ref` on a component works very similar to using `ref` on a native element. You can pass it a variable to be assigned or a callback function. +Birçok durumda, bir bileşenin içinden bir üst bileşene ref göndermek isteyebilirsiniz. Bunu yapmanın yolu yine `ref` attribute'unu kullanmaktır. Dışarıdan bakıldığında, bir bileşen üzerinde `ref` kullanmak, yerel bir öğe üzerinde ref kullanmaya çok benzer. Dolayısıyla atanacak bir değişken veya bir callback fonksiyonu iletebilir. -However, it is the component author's responsibility to connect that `ref` to an internal element to forward it back up. To do so, we leverage `props.ref`. This is a callback form of `ref` if either type of `ref` is given, but this detail is mostly hidden from you as you will more than likely just be assigning it directly to the `ref` attribute of one of the elements or components in this component's JSX. +Ancak, geliştiricinin bu `ref`'i geri iletilmek üzere, bileşen içerisinde bir elemana bağlaması gerekir. Bunun için `props.ref` kullanımından yararlanırız. Bu her iki `ref` türü de verildiği takdirde, `ref`' in callback formudur, fakat genelde siz bunu JSX elemanlarından birine veya bir bileşene `ref` attribute'u olarak doğrudan atayacağınız için çoğunlukla bu detay sizden gizlenir. -To get the logo animating again, we need to forward the ref from `canvas.tsx`: +Logoyu tekrar hareket ettirmek için ref'i `canvas.tsx`'ten iletmemiz gerekmekte: ```jsx diff --git a/langs/tr/tutorials/bindings_refs/lesson.md b/langs/tr/tutorials/bindings_refs/lesson.md index 0b6cac01..0c932b67 100644 --- a/langs/tr/tutorials/bindings_refs/lesson.md +++ b/langs/tr/tutorials/bindings_refs/lesson.md @@ -1,12 +1,12 @@ -You can always get a reference to a DOM element in Solid through assignment, since JSX creates actual DOM elements. For example: +JSX gerçek DOM elemanları oluşturduğu için Solid'de atama yoluyla her zaman bir DOM elemanına referans alabilirsiniz. Örneğin: ```jsx const myDiv =
    My Element
    ; ``` -However, there is benefit to not breaking your elements out and instead putting them in a single contiguous JSX template, as it allows Solid to better optimize their creation. +Ancak Solid'in eleman oluşturma optimizasyonu açısından, elemanları ayırmamanın ve tek bir bitişik JSX şablonu şeklinde kullanmanın yararı vardır. -Instead you can get a reference to an element in Solid using the `ref` attribute. Refs are basically assignments like the example above, which happen at creation time before they are attached to the document DOM. Just declare a variable, pass it in as a `ref` attribute, and the variable will be assigned to: +Bu durumda `ref` attribute'u ile Solid'deki bir elemanı referans alabilirsiniz. Ref'ler temel olarak yukarıdaki örnekte olduğu gibi birer atamadır, oluşturulma aşamasında yani belge DOM'a eklenmeden önce atanırlar. Bir değişken tanımlayın, `ref` attribute'una atayın ve değişken atanacaktır: ```jsx let myDiv; @@ -14,13 +14,13 @@ let myDiv;
    My Element
    ``` -So let's get a reference to our canvas element and animate it: +Örneğimizde canvas elemanına referans alalım ve animasyon ekleyelim: ```jsx ``` -Refs can also take the form of a callback function. This can be convenient for encapsulating logic, especially when you don't need to wait until the elements are attached. For example: +Ref'ler ayrıca bir callback fonksiyonu biçiminde de kullanılabilir. Böylece, mantığı encapsulate etmek için, özellikle de elemanlar eklenene kadar beklemeniz gerekmediğinde, kullanışlı olabilirler. Örneğin: ```jsx
    /* do something with el... */}>My Element
    diff --git a/langs/tr/tutorials/bindings_spreads/lesson.md b/langs/tr/tutorials/bindings_spreads/lesson.md index aa6c72c6..8b90b1a0 100644 --- a/langs/tr/tutorials/bindings_spreads/lesson.md +++ b/langs/tr/tutorials/bindings_spreads/lesson.md @@ -1,8 +1,8 @@ -Sometimes your components and elements accept a variable number of attributes and it makes sense to pass them down as an object instead of individually. This is especially true when wrapping a DOM element in a component, a common practice when making design systems. +Bazen bileşen veya elemanların kabul ettiği attribute sayıları değişebilir, bu durumda da attribute'ları teker teker aktarmaktansa obje halinde aktarmak daha mantıklı olabilir. Bu durum özellikle tasarım sistemleri oluştururken yaygınca kullanılan, bir DOM elemanını bileşen içerisine sararken geçerlidir. -For this we use the spread operator `...`. +Bunun için spread operatör'ü kullanırız `...`. -We can pass an object with a variable number of properties: +Bu sayede objedeki bütün property'leri aktarabiliriz: ```jsx diff --git a/langs/tr/tutorials/bindings_style/lesson.md b/langs/tr/tutorials/bindings_style/lesson.md index 669a7eee..08e954b5 100644 --- a/langs/tr/tutorials/bindings_style/lesson.md +++ b/langs/tr/tutorials/bindings_style/lesson.md @@ -1,14 +1,14 @@ -The `style` attribute in Solid accepts either style strings or objects. -However the object form differs from `Element.prototype.style` and instead is a wrapper for calling `style.setProperty`. This means that keys take the dash-case form, like "background-color" rather than "backgroundColor", and that any units must be explicitly provided (e.g., `width: 500px` rather than `width: 500`). +Solid'deki style attribute'u style string'leri veya objeleri kabul eder. +Ancak nesne formu `Element.prototype.style`'dan farklıdır, aslında `style.setProperty`'yi çağıran bir sarıcıdır (wrapper). Sonuç olarak anahtarlar (key) dash-case yazılır, örneğin "backgroundColor" yerine "background-color" kullanılmalıdır. Ayrıca herhangi bir birim açıkça belirtilmelidir (`width: 500` geçersiz olacaktır, doğru kullanım ise: `width: 500px` şeklindedir) -This also means that we have the ability to set CSS variables: +Bu aynı zamanda CSS değişkenleri atayabileceğimiz anlamına da gelir: ```js
    ``` -Let's animate our div with a few inline styles: +Div'imizi bir kaç satır içi (inline) style ile hareketli hale getirelim: ```jsx
    Date: Wed, 19 Oct 2022 20:49:11 +0300 Subject: [PATCH 12/17] docs(tr): translate tutorials/props --- langs/tr/tutorials/props_children/lesson.md | 18 +++++++++--------- langs/tr/tutorials/props_defaults/lesson.md | 8 ++++---- langs/tr/tutorials/props_split/lesson.md | 17 +++++++---------- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/langs/tr/tutorials/props_children/lesson.md b/langs/tr/tutorials/props_children/lesson.md index d277a2be..9c8b381c 100644 --- a/langs/tr/tutorials/props_children/lesson.md +++ b/langs/tr/tutorials/props_children/lesson.md @@ -1,33 +1,33 @@ -Part of what makes Solid so performant is that our components are basically just function calls. The way we propagate updates is that the compiler wraps potentially reactive expressions in object getters. You can picture the compiler to output: +Solid'i bu kadar performanslı yapan şeylerden birisi de bileşenlerin temelde sadece fonksiyon çağrısı olmasıdır. Solid'te güncellemelerin yayılması, derleyicinin potansiyel olarak reaktif ifadeleri obje getter'larına sarması ile olur. Derleyicinin çıktısını aşağıdaki gibi düşünebilirsiniz: ```jsx -// this JSX +// aşağıdaki JSX -// to become +// buna dönüşmekte MyComp({ get dynamic() { return mySignal() }, get children() { return Child() } }); ``` -This means that these props are evaluated lazily. Their access is deferred until where they are used. This retains reactivity without introducing extraneous wrappers or synchronization. However, it means that repeat access can lead to recreating child components or elements. +Bunun anlamı props'ların lazy olarak değerlendirilmesidir (evaluate) görüyorsunuz. Erişimleri kullanılacakları ana kadar gerçekleşmez. Bu sayede, ek wrapper veya senkronizasyon olmaksızın reaktivite korunur. Ancak bu, tekrarlı erişimin, alt bileşenlerin veya elemanların yeniden oluşturulmasına yol açabileceği anlamına gelir. -The vast majority of the time you will just be inserting props into the JSX so there is no problem. However, when you work with children, you need to be careful to avoid creating the children multiple times. +Genellikle JSX'e sadece prop'lar ekleneceği için sorun oluşmamaktadır ancak, child (alt) elemanlarla çalışırken, elemanları defalarca tekrar oluşturmaktan kaçınmak için dikkatli olmanız gerekir. -For that reason, Solid has the `children` helper. This method both creates a memo around the `children` prop and resolves any nested child reactive references so that you can interact with the children directly. +Bu sebeple, Solid `children` helper'ını sunar. Bu metot hem `children` prop etrafında bir memo oluşturur hem de iç içe geçmiş child reactive referanslarını çözer, böylece child'lar ile doğrudan etkileşime girilebilir. -In the example, we have a dynamic list and we want to set the items' `color` style property. If we interacted with `props.children` directly, not only would we create the nodes multiple times, but we'd find `props.children` to be a function, the Memo returned from ``. +Örneğimizde, dinamik bir listemiz var ve elemanların `color` style property'sini ayarlamak ayarlamak istiyoruz. Doğrudan `props.children` ile etkileşime girersek, yalnızca node'ları defalarca oluşturmakla kalmaz, aynı zamanda da `props.children`'i ``'dan döndürülen memo gibi bir fonksiyon olarak bulurduk. -Instead let's use the `children` helper inside `colored-list.tsx`: +Bunun yerine `children` helper'ını `colored-list.tsx` içerisinde kullanalım: ```jsx export default function ColoredList(props) { const c = children(() => props.children); return <>{c()} } ``` -Now to update our elements, let's create an Effect: +Şimdi de elemanlarımızı güncelleyecek bir Effect oluşturalım: ```jsx createEffect(() => c().forEach(item => item.style.color = props.color)); ``` diff --git a/langs/tr/tutorials/props_defaults/lesson.md b/langs/tr/tutorials/props_defaults/lesson.md index 2dfcc9c9..8100f377 100644 --- a/langs/tr/tutorials/props_defaults/lesson.md +++ b/langs/tr/tutorials/props_defaults/lesson.md @@ -1,10 +1,10 @@ -Props are what we call the object that is passed to our component function on execution that represents all the attributes bound to its JSX. Props objects are readonly and have reactive properties which are wrapped in Object getters. This allows them to have a consistent form regardless of whether the caller used signals, signal expressions, or static values. You access them by `props.propName`. +Props, bileşen fonksiyonumuza aktarılabilen, JSX'e bağlı tüm attribute'ları temsil eden objeye verdiğimiz isimdir. Props objeleri salt okunurdur ve Object getter'larına sarılmış reaktif özelliklere sahiplerdir. sayede, çağıranın sinyal, sinyal ifadesi veya statik değer kullanmasına bağlı olmadan tutarlı bir biçimde olmalarını sağlanır. Ulaşmak için `props.propName` kullanılır. -For this reason it is also very important to not just destructure props objects, as that would lose reactivity if not done within a tracking scope. In general accessing properties on the props object outside of Solid's primitives or JSX can lose reactivity. This applies not just to destructuring, but also to spreads and functions like `Object.assign`. +Bu nedenle props objelerini yalnızca destructure ederek kullanmamak önemlidir, çünkü, bu bir izlenme kapsamı içerisinde yapılmazsa reaktivite kaybolacaktır. Genel olarak, props objesi üzerindeki property'lere özellikle Solid'in primitifleri veya JSX dışında erişmek reaktiviteyi kaybetmekle sonuçlanabilir. Bu sadece destructing için değil, aynı zamanda `Object.assign` gibi spread ve fonksiyonlar için de geçerlidir. -Solid has a few utilities to help us when working with props. The first is `mergeProps`, which merges potentially reactive objects together (like a nondestructive `Object.assign`) without losing reactivity. The most common case is when setting default props for our components. +Solid, props ile çalışırken bize yardımcı olacak bazı utility'lere sahiptir. Bunlardan birincisi, potansiyel olarak reaktif objeleri reaktiviteyi kaybetmeden birleştiren `mergeProps`tur. (`Object.assign` benzeri). En yaygın kullanımı bileşenlerimiz için varsayılan prop'ları atamaktır. -In the example, in `greetings.tsx`, we inlined the defaults in the template, but we could also use `mergeProps` to keep reactive updates even when setting defaults: +Örneğimizde, `greetings.tsx` dosyasında varsayılanları satır içinde kullandık, ek olarak `mergeProps`'u da kullanarak, reaktiviteyi koruyabilir ve güncellemelerin işlenmesini sağlayabiliriz. ```jsx const merged = mergeProps({ greeting: "Hi", name: "John" }, props); diff --git a/langs/tr/tutorials/props_split/lesson.md b/langs/tr/tutorials/props_split/lesson.md index 1593e718..3bdf4d9c 100644 --- a/langs/tr/tutorials/props_split/lesson.md +++ b/langs/tr/tutorials/props_split/lesson.md @@ -1,14 +1,11 @@ -Merging props isn't the only props operation we might want to do. +Props için birleştirme işlemi haricinde de yapmak istediğimiz işlemler olacaktır. -Often, we want to split props into groups, so that we can use some of them on -the current component but split off others to pass through to child components. +Genellikle, props gruplara ayrılır ki +gerekenler mevcut bileşende kullanılsın ve diğerleri de alt bileşenlere aktarılsın. -For this purpose, Solid has [`splitProps`](/docs/latest/api#splitprops). It -takes the props object -and -one or more arrays of keys that we want to extract into their own props objects. It returns an array of props objects, one per array of specified keys, plus one props object with any remaining keys. All returned objects preserve reactivity. +Bu kullanım için Solid [`splitProps`](/docs/latest/api#splitprops) fonksiyonuna sahiptir. Argüman olarak props objesini ve kendi props objesine çıkarmak istediğimiz bir veya daha fazla anahtar array'leri alır. Belirtilen anahtarlardaki her bir array için bir tane olmak üzere props objelerinden oluşan bir array, ve kalan anahtarlar ile de bir props objesi döner. Döndürülen bütün objeler reaktivitiyi korumaktadır. -Our example doesn't update when we set the name because of lost reactivity when we destructure in `greeting.tsx`: +Örneğimiz isim belirlesek de güncellenmiyor, çünkü reaktivite `greeting.tsx` i destructure ederken kaybedilmiş: ```jsx export default function Greeting(props) { const { greeting, name, ...others } = props; @@ -16,11 +13,11 @@ export default function Greeting(props) { } ``` -Instead, we can maintain reactivity with `splitProps`: +Bunun yerine `splitProps` ile reaktiviteyi bu şekilde koruyabiliriz: ```jsx export default function Greeting(props) { const [local, others] = splitProps(props, ["greeting", "name"]); return

    {local.greeting} {local.name}

    } ``` -Now the button works as expected. \ No newline at end of file +Artık buton beklediğimiz gibi çalışıyor. \ No newline at end of file From 040b3e41126fd5a2dabbe44cfa895a8d08ececfa Mon Sep 17 00:00:00 2001 From: Wralith Date: Thu, 20 Oct 2022 00:13:36 +0300 Subject: [PATCH 13/17] docs(tr): fix typo in props_children --- langs/tr/tutorials/props_children/lesson.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/langs/tr/tutorials/props_children/lesson.md b/langs/tr/tutorials/props_children/lesson.md index 9c8b381c..d7b727bf 100644 --- a/langs/tr/tutorials/props_children/lesson.md +++ b/langs/tr/tutorials/props_children/lesson.md @@ -12,11 +12,11 @@ MyComp({ get children() { return Child() } }); ``` -Bunun anlamı props'ların lazy olarak değerlendirilmesidir (evaluate) görüyorsunuz. Erişimleri kullanılacakları ana kadar gerçekleşmez. Bu sayede, ek wrapper veya senkronizasyon olmaksızın reaktivite korunur. Ancak bu, tekrarlı erişimin, alt bileşenlerin veya elemanların yeniden oluşturulmasına yol açabileceği anlamına gelir. +Yani props lazy olarak değerlendirilir (lazily evaluate edilir). Yani kullanılacakları ana kadar bir erişim gerçekleşmez. Bu sayede, ek wrapper veya senkronizasyon olmaksızın reaktivite korunur. Ancak bu durum; tekrarlı erişimin, alt bileşenlerin veya elemanların yeniden oluşturulmasına yol açabileceği anlamına gelir. Genellikle JSX'e sadece prop'lar ekleneceği için sorun oluşmamaktadır ancak, child (alt) elemanlarla çalışırken, elemanları defalarca tekrar oluşturmaktan kaçınmak için dikkatli olmanız gerekir. -Bu sebeple, Solid `children` helper'ını sunar. Bu metot hem `children` prop etrafında bir memo oluşturur hem de iç içe geçmiş child reactive referanslarını çözer, böylece child'lar ile doğrudan etkileşime girilebilir. +Bu sebeple, Solid `children` helper'ını sunar. Bu metot hem `children` prop'u etrafında bir memo oluşturur hem de iç içe geçmiş child reactive referanslarını çözer, böylece child'lar ile doğrudan etkileşime girilebilir. Örneğimizde, dinamik bir listemiz var ve elemanların `color` style property'sini ayarlamak ayarlamak istiyoruz. Doğrudan `props.children` ile etkileşime girersek, yalnızca node'ları defalarca oluşturmakla kalmaz, aynı zamanda da `props.children`'i ``'dan döndürülen memo gibi bir fonksiyon olarak bulurduk. From 8ce14c7d1367e71f5855002cd828d4e60d9a53de Mon Sep 17 00:00:00 2001 From: Wralith Date: Thu, 20 Oct 2022 16:52:36 +0300 Subject: [PATCH 14/17] docs(tr): translate tutorials/stores --- langs/tr/tutorials/stores_context/lesson.md | 10 +++++----- .../tr/tutorials/stores_createstore/lesson.md | 15 +++++++------- langs/tr/tutorials/stores_immutable/lesson.md | 20 +++++++++---------- langs/tr/tutorials/stores_mutation/lesson.md | 8 ++++---- .../stores_nested_reactivity/lesson.md | 14 ++++++------- langs/tr/tutorials/stores_nocontext/lesson.md | 14 ++++++------- 6 files changed, 41 insertions(+), 40 deletions(-) diff --git a/langs/tr/tutorials/stores_context/lesson.md b/langs/tr/tutorials/stores_context/lesson.md index e76d779e..2a0ba973 100644 --- a/langs/tr/tutorials/stores_context/lesson.md +++ b/langs/tr/tutorials/stores_context/lesson.md @@ -1,10 +1,10 @@ -Solid provides a Context API to pass data around without relying on passing through props. This is useful for sharing Signals and Stores. Using Context has the benefit of being created as part of the reactive system and managed by it. +Solid verileri props olarak geçirmeye gerek olmaksızın aktarmak için bir Context API sağlar. Bu, sinyalleri ve store'ları paylaşmak için kullanışlı olabilir. Context kullanımı, reaktif sistemin bir parçası olarak oluşturulma ve sistem tarafından yönetilme avantajına sahiptir. -To get started we create a Context object. This object contains a `Provider` component used to inject our data. However, it is common practice to wrap the `Provider` components and `useContext` consumers with versions already configured for the specific Context. +Başlamak için bir Context objesini oluşturuyoruz. Bu obje, verilerimizi enjekte etmek için kullanılan bir `Provider` bileşeni içerir. Bununla birlikte, `Provider` bileşenlerini ve `useContext` consumer'ların belirli Context için önceden yapılandırılmış sürümleri ile sarmak yaygın bir kullanımdır. -And that's exactly what we have in this tutorial. You can see the definition for a simple counter store in the `counter.tsx` file. +Bu derste de tam olarak bunu yapıyoruz. Basit bir counter (sayaç) store'unun tanımını `counter.tsx` dosyasında görebilirsiniz. -To use context, first let's wrap our App component to provide it globally. We will use our wrapped `CounterProvider`. In this case let's give it an initial count of 1. +Context'i kullanmak için öncelikle App bileşenimizi global olarak sağlamak üzere saralım. Sarmaladığımız `CounterProvider`'ı kullanacağız. Son olarak count'u başlangıç değeri 1 olacak şekilde düzenleyelim. ```jsx render(() => ( @@ -14,7 +14,7 @@ render(() => ( ), document.getElementById("app")); ``` -Next we need to consume the counter context in our `nested.tsx` component. We do this by using the wrapped `useCounter` consumer. +Sonra, `nested.tsx` bileşenimizdeki counter context'ini consume etmemiz gerekiyor. Bunu, sarılmış `useCounter` consumer'ini kullanarak yapabiliriz: ```jsx const [count, { increment, decrement }] = useCounter(); diff --git a/langs/tr/tutorials/stores_createstore/lesson.md b/langs/tr/tutorials/stores_createstore/lesson.md index 3b42d41c..26f7c0b5 100644 --- a/langs/tr/tutorials/stores_createstore/lesson.md +++ b/langs/tr/tutorials/stores_createstore/lesson.md @@ -1,14 +1,15 @@ -Stores are Solid's answer to nested reactivity. They are proxy objects whose properties can be tracked and can contain other objects which automatically become wrapped in proxies themselves, and so on. +Store'lar Sold'in iç içe geçmiş reaktiviteye cevabıdır. Property'leri takip edilebilen proxy objelerdir ve başka objeler içerebilirler. İçerdiği objeler de otomatik olarak proxy ile sarılır. -To keep things light, Solid creates underlying Signals only for properties that are accessed under tracking scopes. And so, all Signals in Stores are created lazily as requested. +İşleri hafif tutmak için Solid, yalnızca izleme kapsamları altında erişilen property'ler için temel sinyaller oluşturur. Bu sayede Store'lardaki tüm sinyaller istenildiği gibi lazy şekilde oluşturulur. -The `createStore` call takes the initial value and returns a read/write tuple similar to Signals. The first element is the store proxy which is readonly, and the second is a setter function. +`createStore` fonksiyonu, başlangıç değeri alır ve sinyallere benzer bir okuma/yazma tuple'ı döndürür. İlk eleman salt okunur store proxy'sidir, ikinci ise bir setter fonksiyonudur. -The setter function in its most basic form takes an object whose properties will be merged with the current state. It also supports path syntax so that we can do nested updates. In this way we can still maintain control of our reactivity but do pinpoint updates. +Setter fonksiyonu en temel haliyle, property'leri mevcut durumla birleşecek olan bir obje alır. Ayrıca iç içe güncellemeler yapabilmemiz için bir path syntax'ı da destekler. Bu sayede hem reaktivitenin kontrolünü koruyabilir, hem de nokta atışı güncellemeler yapabiliriz. -> Solid's path syntax has many forms and includes some powerful syntax to do iteration and ranges. Refer to the API documentation for a full reference. +> Sold'in path syntax'ının bir çok formu vardır ve yineleme ve aralıklar yapmak için bazı güçlü syntax'lar içerir. Tüm kapsamını görmek için API dokümantasyonuna bakın. Let's look at how much easier it is to achieve nested reactivity with a Store. We can replace the initialization of our component with this: +Gelin Store ile iç içe geçmiş reaktifliğin ne kadar kolay oluşturulduğuna bakalım. Bileşenimizdeki ilgili kısmı değiştirelim: ```js const [todos, setTodos] = createStore([]); @@ -24,6 +25,6 @@ const toggleTodo = (id) => { }; ``` -We make use of the Store's path syntax with function setters that allow us to take the previous state and return the new state on nested values. +Store'un path syntax'ını önceki state'i almamıza ve iç içe geçmiş değerlerde yeni state'i döndürmemizi olanak tanıyan fonksiyon setter'lar ile kullanıyoruz. -And that's it. The rest of the template will already react granularly (check the Console on clicking the checkbox). +Ve hepsi bu kadar, şablonun geri kalanı da tepki verecektir (onay kutusunu tıklandığında Konsolu kontrol edin) \ No newline at end of file diff --git a/langs/tr/tutorials/stores_immutable/lesson.md b/langs/tr/tutorials/stores_immutable/lesson.md index d7ea8f24..5a83ada8 100644 --- a/langs/tr/tutorials/stores_immutable/lesson.md +++ b/langs/tr/tutorials/stores_immutable/lesson.md @@ -1,8 +1,8 @@ -Stores are most often created in Solid using Solid's Store proxies. Sometimes we wish to interface with immutable libraries like Redux, Apollo, or XState and need to perform granular updates against these. +Store'lar çoğunlukla Solid'in Store proxy'leri kullanılarak oluşturulur. Bazen Redux, Apollo veya XState gibi immutable kütüphaneler ile interface'ler oluşturmak isteyebilirsiniz ve bunlar için parçalı (granular) güncellemeler yapmanız gerekir. -In the example, we have a basic wrapper around Redux. You can see the implementation in `useRedux.tsx`. The definition of the store and the actions are in the remaining files. +Örneğimizde `useRedux.tsx` dosyasında görebileceğiniz temel bir Redux wrapper'ımız var. Store tanımı ve action'lar da diğer dosyalarda yer almakta. -The core behavior is that we created a Store object and subscribe to the Redux store to update state on update. +Temel kullanım, bir store objesi oluşturmamız ve güncelleme sırasında durumu güncellemek için Redux Store'una subscribe olmamızdır. ```js const [state, setState] = createStore(store.getState()); @@ -10,11 +10,11 @@ const unsubscribe = store.subscribe( () => setState(store.getState()) ); ``` -If you click around the demo adding items and checking them off it seems to work pretty well. However, what isn't obvious is that the rendering is inefficient. Notice the console.log not only on create but whenever you check the box. +Demo'da ögelerin eklenmesi veya işaretlenmesi iyi çalışır gibi görünüyor. Ancak, verimsiz render'lar yok sayılmamalıdır. Dikkat ederseniz console.log sadece öge eklendiğinde değil ögeler işaretlendiğinde de oluşmakta. -The reason is that Solid doesn't diff by default. It assumes the new item is new and replaces it. If your data changes granularly, you don't need to diff. But what if you do? +Bunun nedeni Solid'in varsayılan olarak farklılaşmıyor (diff) oluşudur. Yeni ögenin yeni olduğunu varsayar ve değiştirir. Veriler parçalı değişiyorsa farklılaştırmaya gerek olmaz. Ama ya gerekirse? -Solid provides a diffing method `reconcile` that enhances the `setStore` call and lets us diff the data from these immutable sources, only notifying the granular updates. +Solid, `setStore` çağrısını geliştiren ve bu immutable kaynaklardan gelen verileri yalnızca parçalı güncellemeleri bildirerek farklılaştırmamızı sağlayan bir yöntem olarak `reconcile` fonksiyonunu sağlar. Let's update that code to: ```js @@ -23,11 +23,11 @@ const unsubscribe = store.subscribe( () => setState(reconcile(store.getState())) ); ``` -Now the example works as you'd expect, only running the create code on create. +Şimdi örneğimizde beklediğimiz gibi Create sadece öğe eklenirken konsol'da yazdırılıyor. -This isn't the only way to solve this and you've seen some frameworks have a `key` property on their template loop flows. The problem is that by making that a default part of the templating, you always need to run list reconciliation and always have to diff all the children for potential changes, even in compiled frameworks. A data-centric approach not only makes this applicable outside of templating but makes it opt in. When you consider that internal state management doesn't need this, it means we default to having the best performance. +Tek çözüm elbette bu değil, bazı framework'lerde `key` property'sinin döngü içerisindeki elemanlarda kullanıldığını görmüşsünüzdür. Sorun şu ki, bu davranışı varsayılan hale getirdiğinizde, her zaman liste hesaplaması yapmanız ve derlenmiş framework'lerde bile, olası değişiklikler için tüm alt elemanları her zaman farklılaştırmanız gerekir. Veri merkezli bir yaklaşım, bunu yalnızca template dışı uygulanabilir hale getirmez aynı zamanda da daha tercih edilebilir hale getirir. Internal state yönetiminin buna ihtiyaç duymadığını da göz önünde bulundurduğumuzda, Solid'in en performanslı yolu varsayılan olarak sunduğunu unutmayalım. -Of course, there's no problem using `reconcile` when you need it. Sometimes a simple reducer makes for a great way to organize data updates. `reconcile` shines here, making your own `useReducer` primitive: +Elbette, ihtiyaç duyulduğunda `reconcile` kullanmakta bir sorun yoktur. Bazen basit bir reducer, veri güncellemelerini organize etmek için harika bir yöntem sağlayabilir. `reconcile` kendini burada gösterir ve kendi `useReducer` primitiflerinizi oluşturur. ```js const useReducer = (reducer, state) => { @@ -40,4 +40,4 @@ const useReducer = (reducer, state) => { }; ``` -The behavior of `reconcile` is configurable. A custom `key` can be set and there is a `merge` option which ignores structural cloning and only diffs the leaves. \ No newline at end of file +`Reconcile`'ın davranışı yapılandırılabilir. Özel bir key ayarlanabilir, ayrıca yapısal klonlamayı yok sayan ve yalnızca alt parçaları (leaves) farklılaştıran bir birleştirme seçeneği de vardır. \ No newline at end of file diff --git a/langs/tr/tutorials/stores_mutation/lesson.md b/langs/tr/tutorials/stores_mutation/lesson.md index 4dff00de..e392cca8 100644 --- a/langs/tr/tutorials/stores_mutation/lesson.md +++ b/langs/tr/tutorials/stores_mutation/lesson.md @@ -1,8 +1,8 @@ -Solid strongly recommends the use of shallow immutable patterns for updating state. By separating reads and writes we maintain better control over the reactivity of our system without the risk of losing track of changes to our proxy when passed through layers of components. This is much more amplified with Stores compared to Signals. +Solid şiddetle shallow immutable modellerin kullanmasını tavsiye eder. Okumaları ve yazmaları ayırarak, bileşen katmanlarından geçerken proxy'mizdeki değişkenlerin izini kaybetme riski olmadan sistemimizin reaktivitesi üzerinde daha iyi kontrol sağlarız. Sinyallere kıyasla Store'larda bu kullanımın getirisi çok daha yüksek olacaktır. -Sometimes, however, mutation is just easier to reason about. That's why Solid provides an Immer inspired `produce` store modifier that allows you to mutate a writable proxy version of your Store object inside your `setStore` calls. +Ancak bazen mutation'ları kullanmak, daha doğrusu mutation'lar kullanıyormuş gibi mantık yürütmek daha kolaydır. Bu nedenle Solid, `setStore` çağrıları içinde Store objesinin yazılabilir bir proxy sürümünü mutate edebilmenize olanak tanıyan Immer'den ilham alan bir `produce` store değiştiricisi sunar. -This is a nice tool to have to allow small zones of mutation without relinquishing control. Let's use `produce` on our Todos example by replacing our event handler code with: +`produce`, kontrolü elden bırakmadan küçük mutate alanlarına izin vermek için güzel bir araçtır. Event handler'ı şu şekilde değiştirerek `produce`'u Todo örneğimizde kullanalım: ```jsx const addTodo = (text) => { @@ -20,4 +20,4 @@ const toggleTodo = (id) => { }; ``` -While `produce` with Stores probably handles the vast majority of cases, Solid also has a mutable Store object that is available from `createMutable`. While not the recommended approach for internal APIs, it is sometimes useful for interop or compatibility with 3rd party systems. +Store ve `produce` kullanımların bir çoğu için yeterli olacaktır, Solid ayrıca `createMutable` ile kullanılabilen bir mutable Store objesine sahiptir. Internal API'lar için önerilen bir yaklaşım olmasa da bazen interop veya 3. parti sistemlerle uyumluluk için kullanışlı olacaktır. diff --git a/langs/tr/tutorials/stores_nested_reactivity/lesson.md b/langs/tr/tutorials/stores_nested_reactivity/lesson.md index 8a3a54c6..6f6fc5ec 100644 --- a/langs/tr/tutorials/stores_nested_reactivity/lesson.md +++ b/langs/tr/tutorials/stores_nested_reactivity/lesson.md @@ -1,7 +1,7 @@ -One of the reasons for fine-grained reactivity in Solid is that it can handle nested updates independently. You can have a list of users and when we update one name we only update a single location in the DOM without diffing the list itself. Very few (even reactive) UI frameworks can do this. - -But how do we accomplish this? In the example we have a list of todos in a signal. In order to mark a todo as complete, we would need to replace the todo with a clone. This is how most frameworks work, but it's wasteful as we rerun the list diffing and we recreate the DOM elements as illustrated in the `console.log`. +İç içe güncellemeleri bağımsız olarak işlenebilir olması, Solid'deki incelikli reaktivitenin nedenlerinden biridir. Bir kullanıcı listesine sahip olabilirsiniz, bunun içerisindeki bir ismi güncellediğimizde listenin kendisini değiştirilmeden sadece DOM'daki tek bir konum güncellenir. Bunu çok az framework (reaktif olsalar bile) başarabilmiştir. +Peki bunu nasıl başarıyoruz? Örnekte bir sinyal içerisinde todo listemiz var. Bir todo'yu tamamlandı olarak işaretlemek için, todo bir klon ile değiştirilmelidir. Çoğu framework bu şekilde çalışır, ancak listeyi farklılaştırarak yeniden çalıştırdığımız ve bunun sonucunda - `console.log` ile gösterildiği gibi - DOM elemanları yeniden oluşturulduğu için bu gereksiz bir yük oluşturur. + ```js const toggleTodo = (id) => { setTodos( @@ -10,7 +10,7 @@ const toggleTodo = (id) => { }; ``` -Instead, in a fine-grained library like Solid, we initialize the data with nested Signals like this: +Bunun yerine, Solid ile biz veriyi iç içe geçmiş sinyaller ile oluşturabiliriz: ```js const addTodo = (text) => { @@ -19,7 +19,7 @@ const addTodo = (text) => { }; ``` -Now we can update the completion state by calling `setCompleted` without any additional diffing. This is because we've moved the complexity to the data rather than the view. And we know exactly how the data changes. +Artık `setCompleted` fonksiyonunu çağırarak herhangi bir ek farklılaştırma oluşturmadan state'i güncelleyebiliriz. Bunun nedeni, karmaşıklığı view'dan alıp veriye taşımış olmamızdır ve verinin nasıl değiştiğini tam olarak bilmekteyiz. ```js const toggleTodo = (id) => { @@ -27,6 +27,6 @@ const toggleTodo = (id) => { if (todo) todo.setCompleted(!todo.completed()) } ``` -If you change the remaining references of `todo.completed` to `todo.completed()`, the example should now only run the `console.log` on creation and not when you toggle a todo. +Kalan `todo.completed` referanslarını `todo.completed()` ile değiştirirseniz, örnek artık bir todo'yu değiştirdiğinizde değil, yalnızca oluşturduğunuzda `console.log`'u çalıştırmaktadır. -This of course requires some manual mapping and it was the only choice available to us in the past. But now, thanks to proxies, we can do most of this work in the background without manual intervention. Continue to the next tutorials to see how. +Bu elbette bazı manuel eşlemeler gerektir ve geçmişte bizim için mevcut olan tek seçenekti. Ancak artık, proxy'ler ile bu işin çoğunu manuel müdahale olmaksızın arka planda yapabiliriz. Nasıl yapıldığını görmek için sonraki eğitimlerle devam edin. diff --git a/langs/tr/tutorials/stores_nocontext/lesson.md b/langs/tr/tutorials/stores_nocontext/lesson.md index e2051130..f85fc34e 100644 --- a/langs/tr/tutorials/stores_nocontext/lesson.md +++ b/langs/tr/tutorials/stores_nocontext/lesson.md @@ -1,22 +1,22 @@ -Context is a great tool for stores. It handles injection, ties ownership to the reactive graph, automatically manages disposal, and has no render overhead given Solid's fine-grained rendering. +Context, store'lar için harika bir araçtır. Injection'u yönetir, ownership'i reaktif grafiğe bağlar, otomatik olarak disposal'ları yönetir ve tüm bunları yaparken render için ek yük oluşturmaz. -Sometimes context is overkill, though; an alternative is to use the reactive system directly. For example, we can build a global reactive data store by creating a signal in a global scope, and `export`ing it for other modules to use: +Yine de bazen context kullanmak aşırıya kaçabilir, alternatifi reaktif sistemi doğrudan kullanmaktır. Örneğin, global kapsamda bir sinyal oluşturarak bunu diğer modüllerin kullanması için `export` edip bir reaktif data store oluşturabiliriz. ```js import { createSignal } from 'solid-js'; export default createSignal(0); -// somewhere else: +// kullanmak istediğimiz başka bir yer: import counter from './counter'; const [count, setCount] = counter; ``` -Solid's reactivity is a universal concept. It doesn't matter if it is inside or outside components. There is no separate concept for global vs local state. It is all the same thing. +Solid'in reaktivitesi evrensel bir kavramdır, bileşenlerin içinde ya da dışında olması fark etmez. Global veya local state'için ayrı bir konsept yoktur ve hepsi birbirine denktir. -The only restriction is that all computations (Effects/Memos) need to be created under a reactive root (`createRoot`). Solid's `render` does this automatically. +Tek kısıtlama, tüm hesaplamaların (Efektler/Memolar) reaktif bir kök (`createRoot`) altında oluşturulması gereksinimidir. Solid'in render'ı bunu otomatik yapmaktadır. -In this tutorial `counter.tsx` is such a global store. We can use it by modifying our component in `main.tsx` to: +Bu örnekte `counter.tsx` global bir store'dur. `main.tsx` içinde, bileşenimizi şu şekilde düzenleyerek kullanabiliriz: ```jsx const { count, doubleCount, increment } = counter; @@ -28,4 +28,4 @@ return ( ); ``` -So when using your own more complicated global stores that contain computations, be sure to create a root. Or better yet, do yourself a favor and just use Context. +Sonuç olarak, hesaplamalar içeren karmaşık bir global store oluşturacağınız zaman bir root oluşturduğunuza dikkat edin. Ya da daha iyisi kendinize bir iyilik yapın ve sadece context kullanın. From d3e91d07ecd3403b45ddb44a117836f51da0bda9 Mon Sep 17 00:00:00 2001 From: Wralith Date: Fri, 21 Oct 2022 00:19:50 +0300 Subject: [PATCH 15/17] docs(tr): translate tutorials/reactivity --- langs/tr/tutorials/reactivity_batch/lesson.md | 8 ++++---- langs/tr/tutorials/reactivity_on/lesson.md | 4 ++-- langs/tr/tutorials/reactivity_untrack/lesson.md | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/langs/tr/tutorials/reactivity_batch/lesson.md b/langs/tr/tutorials/reactivity_batch/lesson.md index a8789813..9a23e7cf 100644 --- a/langs/tr/tutorials/reactivity_batch/lesson.md +++ b/langs/tr/tutorials/reactivity_batch/lesson.md @@ -1,8 +1,8 @@ -Solid's reactivity is synchronous which means, by the next line after any change, the DOM will have updated. And for the most part this is perfectly fine, as Solid's granular rendering is just a propagation of the update in the reactive system. Unrelated changes "rendering" twice don't actually mean wasted work. +Solid'in reaktivitesi synchronous'tur, yani DOM herhangi bir değişiklikten sonraki satırda güncellenmiş hale gelir. Solid'in granular rendering'i sadece reaktif sistemdeki güncellemenin bir yayılımı olduğu için bu çoğunlukla mükemmeldir. İlişkisi bulunmayan değişikliklerin iki kez "render edilmesi" aslında bunun boşuna olduğu anlamına gelmez. -What if the changes are related? Solid's `batch` helper allows to queue up multiple changes and then apply them all at the same time before notifying their observers. +Peki ya değişiklikler arasına ilişki varsa? Solid'in `batch` helper'i birden fazla değişikliği sıraya koymaya ve gözlemcilerine bildirmeden önce hepsini aynı anda uygulamaya izin verir. -In this example, we are assigning both names on a button click and this triggers our rendered update twice. You can see the logs in the console when you click the button. So let's wrap the `set` calls in a batch. +Örneğimizde, bir butona tıklandığında her iki ismi de atıyoruz ve bu, işlenen render'lanmış güncellemeyi iki kez tetikliyor. Butona tıkladığınızda log'ları konsolda görebilirsiniz. Öyleyse `set` çağrılarını bir `batch` içerisine saralım. ```js const updateNames = () => { @@ -13,4 +13,4 @@ In this example, we are assigning both names on a button click and this triggers }) } ``` -And that's it. Now we only notify once for the whole changeset. \ No newline at end of file +Ve bu kadar, bütün değişiklikler artık bir kere bildiriliyor. \ No newline at end of file diff --git a/langs/tr/tutorials/reactivity_on/lesson.md b/langs/tr/tutorials/reactivity_on/lesson.md index 1d9deffc..15a7e3ae 100644 --- a/langs/tr/tutorials/reactivity_on/lesson.md +++ b/langs/tr/tutorials/reactivity_on/lesson.md @@ -1,6 +1,6 @@ -For convenience, Solid has an `on` helper that enables setting explicit dependencies for our computations. This is mostly used as a terse way to be even more explicit about which Signals are tracked (and not track any other Signals, even if they are read). In addition, `on` provides a `defer` option that allows the computation not to execute immediately and only run on first change. +Kolaylık sağlamak için Solid, hesaplamalarımız için spesifik bağımlılıklar oluşturmayı sağlayan bir `on` helper'ına sahiptir. Bu çoğunlukla hangi Sinyallerin takip edileceği konusunda daha da açık olmanın (ve okunsalar bile diğer sinyalleri track etmemenin) kısa bir yolu olarak kullanılır. Ayrıca `on` hesaplamanın hemen yürütülmesini ve yalnızca ilk değişiklikte çalıştırılmasını sağlayan bir `defer` seçeneği sunar. -Let's have our Effect run only when `a` updates, and defer execution until the value changes: +Örneğimizde, Effect'in yalnızca `a` değeri güncellendiğinde çalışmasını ve bu değer değişene kadar çalışmayı ertelemesini sağlayalım: ```js createEffect(on(a, (a) => { diff --git a/langs/tr/tutorials/reactivity_untrack/lesson.md b/langs/tr/tutorials/reactivity_untrack/lesson.md index 061f55fd..e81ae7de 100644 --- a/langs/tr/tutorials/reactivity_untrack/lesson.md +++ b/langs/tr/tutorials/reactivity_untrack/lesson.md @@ -1,12 +1,12 @@ -It's sometimes desirable to have Signal reads not be tracked, even inside a reactive context. Solid provides the `untrack` helper as a way to prevent the wrapping computation from tracking any reads. +Bazen reaktif bir Context içinde olsa bile Signal okumalarının track edilmemesi istenilebilir. Solid, `untrack` helper'i ile sarılmış işlemlerin okumaları track etmesini engelleyebilir. -Let's suppose we did not want to log in our example when `b` changes. We can untrack the `b` signal by changing our effect to the following: +Örneğimizde `b` değiştiğinde loglamak istemediğimizi varsayalım. Signal'i aşağıdaki şekilde değiştirerek `b` sinyalinin takibini kaldırabiliriz (untrack). ```js createEffect(() => { console.log(a(), untrack(b)); }); ``` -Since Signals are functions, they can be passed directly, but `untrack` can wrap functions with more complex behavior. +Sinyaller fonksiyon olduğu için doğrudan aktarılabilirler, ancak `untrack` daha karmaşık davranışa sahip fonksiyonları da sarabilir. -Even though `untrack` disables tracking of reads, it has no effect on writes which still happen and notify their observers. +`untrack` okumaların izlenmesini devre dışı bırakıyor olsa da, hala gerçekleşen ve gözlemcilerini bildiren yazmalar üzerinde hiçbir etkisi yoktur. From 30ebed73d9428b3c99bad78324eb2296bce888c5 Mon Sep 17 00:00:00 2001 From: Wralith Date: Fri, 21 Oct 2022 23:32:19 +0300 Subject: [PATCH 16/17] docs(tr): translate tutorials/async --- langs/tr/tutorials/async_lazy/lesson.md | 8 ++++---- langs/tr/tutorials/async_resources/lesson.md | 14 +++++++------- langs/tr/tutorials/async_suspense/lesson.md | 14 +++++++------- langs/tr/tutorials/async_suspense_list/lesson.md | 6 +++--- langs/tr/tutorials/async_transitions/lesson.md | 14 +++++++------- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/langs/tr/tutorials/async_lazy/lesson.md b/langs/tr/tutorials/async_lazy/lesson.md index af9fdf45..2eaf565b 100644 --- a/langs/tr/tutorials/async_lazy/lesson.md +++ b/langs/tr/tutorials/async_lazy/lesson.md @@ -1,15 +1,15 @@ -Most bundlers (like Webpack, Rollup, Parcel, Vite) automatically handle code splitting when you use a dynamic import. Solid's `lazy` method allows us to wrap the component's dynamic import for deferred lazy loading. The output is a Component that can be used as normal in our JSX template with the exception that internally it dynamically loads the underlying imported code when it is rendered the first time, halting that branch of rendering until the code is available. +Bütün bundler'lar (Webpack, Rollup, Parcel, Vite) dinamik import'lar kullandığından kod bölme (code splitting) işlemini otomatik olarak gerçekleştirir. Solid'in lazy metodu, ertelenmiş lazy yükleme için bileşenin dinamik import'unu wrap etmenizi sağlar. Çıktı, JSX'te normal bir şekilde kullanılabilen bileşendir ve tek fark ilk kez render edilişinde import ettiği kodu dinamik olarak yüklemesi ve kod elde edilene kadar render branch'ını durdurmasıdır. -To use `lazy`, replace the import statement: +`lazy` kullanmak için aşağıdaki satırı: ```js import Greeting from "./greeting"; ``` -with: +Aşağıdaki ile değiştirelim: ```js const Greeting = lazy(() => import("./greeting")); ``` -This will likely still load too quickly to see. But you add a fake delay if you wish to make the loading more visible. +Büyük olasılıkla hala gözle fark edilemeyecek kadar hızlı olacaktır, fakat yüklenmeyi görmek isterseniz bir miktar sahte gecikme ekleyebilirsiniz. ```js const Greeting = lazy(async () => { diff --git a/langs/tr/tutorials/async_resources/lesson.md b/langs/tr/tutorials/async_resources/lesson.md index fa6079ed..627b69f0 100644 --- a/langs/tr/tutorials/async_resources/lesson.md +++ b/langs/tr/tutorials/async_resources/lesson.md @@ -1,19 +1,19 @@ -Resources are special Signals designed specifically to handle Async loading. Their purpose is wrap async values in a way that makes them easy to interact with in Solid's distributed execution model. This is the opposite to `async`/`await` or generators which provide sequential execution models. The goal is for async to not block execution and not color our code. +Resource'lar özellikle Async yüklemeyi işlemek için tasarlanmış özel Sinyallerdir. Amaçları, asenkron değerleri Sold'in dağıtık yürütme modelinde etkileşime girmelerini kolaylaştıracak şekilde sarmaktır. Bu sıralı modeller sağlayan async/await veya generator'ların tam tersidir. Amacı async'in akışı engellemesinin önüne geçmektir. -Resources can be driven by a source signal that provides the query to an async data fetcher function that returns a promise. The contents of the fetcher function can be anything. You can hit typical REST endpoints or GraphQL or anything that generates a promise. Resources are not opinionated on the means of loading the data, only that they are driven by promises. +Resource'lar, bir promise döndüren async data fetcher fonksiyonuna sorgu sağlayan bir kaynak sinyali tarafından yönlendirilebilir. Fetcher fonksiyonun ne olduğu önemli değildir, yani tipik REST endpoint'ine veya GraphQL'e ya da bir promise üreten herhangi bir şeye ulaşmakta kullanılabilir. Resource'lar verilerin yüklenmesi konusunda bilgi sahibi değillerdir yani promise'e bağlı çalışır ve onun tarafından yönlendirilirler. -The resulting Resource Signal also contains reactive `loading` and `error` properties that make it easy to control our view based on the current status. +Ortaya çıkan Resource sinyali, mevcut duruma göre görüntüyü kontrol etmemizi sağlayan reaktif `loading` ve `error` property'lerini de içerir. -So let's replace our user signal with a resource: +Örneğimizde user sinyalini Resource ile değiştirelim: ```js const [user] = createResource(userId, fetchUser); ``` -It is driven by the `userId` Signal and calls our fetch method on change. Not much else to it. +Ürettiğimiz user, `userId` sinyali tarafından yönetilir ve değişiklik olduğu zaman fetch metodunu çalıştırır, bu kadar. -The second value that comes back from `createResource` contains a `mutate` method for directly updating the internal Signal and a `refetch` method to reload the current query even if the source hasn't changed. +`createResource`'tan dönen ikinci değer, içerideki Signal'i doğrudan güncellemek için bir `mutate` metodu ve kaynak değişmemiş olsa bile mevcut sorguyu yeniden yüklemek için bir `refetch` metodu içerir. ```js const [user, { mutate, refetch }] = createResource(userId, fetchUser); ``` -`lazy` uses `createResource` internally to manage its dynamic imports. +`lazy` içeride `createResource` kullanarak dinamik import'ları yönetir. diff --git a/langs/tr/tutorials/async_suspense/lesson.md b/langs/tr/tutorials/async_suspense/lesson.md index 87159b1b..1152ce95 100644 --- a/langs/tr/tutorials/async_suspense/lesson.md +++ b/langs/tr/tutorials/async_suspense/lesson.md @@ -1,8 +1,8 @@ -While `lazy` and `createResource` can be used on their own, Solid also provides a mechanism for coordinating the display of multiple async events. `Suspense` serves as a boundary that can show a fallback placeholder instead of the partially loaded content as these async events resolve. +`lazy` ve `createResource` kendi başlarına kullanılabilseler de Solid, birden fazla asenkron event'in görüntülenmesini koordine etmek için bir mekanizma da sağlar. `Suspense`, bu asenkron event'ler çözüldükçe kısmen yüklenen içerik yerine yedek bir placeholder tutan bir sınır görevi görür. -This can improve user experience by removing visual jank caused by too many intermediate and partial loading states. `Suspense` automatically detects any descendant async reads and acts accordingly. You can nest as many `Suspense` components as needed and only the nearest ancestor will transform to `fallback` when the `loading` state is detected. +Bu şekilde, çok fazla ara ve kısmi yükleme durumlarının neden olduğu problemleri düzenleyerek kullanıcı deneyimini iyileştirebiliriz. `Suspense` kendisinden sonra gelen asenkron okumaları otomatik olarak algılayıp buna göre hareket eder. İstediğiniz kadar `Suspense` bileşenini iç içe yerleştirebilirsiniz, bu durumda yükleme durumu algılandığında yalnızca en yakın ancestor fallback'ine dönüş yapılacaktır. -Let's add a `Suspense` component to our lazy loading example: +Lazy load örneğimize bir `Suspense` bileşeni ekleyelim: ```jsx <> @@ -13,11 +13,11 @@ Let's add a `Suspense` component to our lazy loading example: ``` -Now we have a loading placeholder. +Artık yükleme durumu için bir placeholder'ımız var. -It's important to note that it's the read of an async derived value that triggers `Suspense`, not the async fetching itself. If a resource signal (including `lazy` components) is not read under the `Suspense` boundary, it will not suspend. +Asenkron fetching'in kendisinin değil de asenkron olarak türemiş bir değerin okunmasının `Suspense`'i tetiklendiğine dikkat etmelisiniz. Eğer bir kaynak sinyali (`lazy` olsa bile) `Suspense` boundary'si altında okunmazsa, suspense işlemi gerçekleşmeyecektir. -`Suspense` in many ways is just a `Show` component that renders both branches. While `Suspense` is vital for asynchronous Server rendering, do not feel the need to jump immediately to using it for client-rendered code. Solid's fine-grained rendering has no additional cost for splitting things manually. +`Suspense` birçok açıdan her iki branch'i de render eden bir `Show` bileşenidir. Asenkron Sunucu render işlemleri için `Suspense` hayati öneme sahip olsa da, client'ta render edilecek kod için hemen `Suspense` kullanma ihtiyacı hissetmeyin. Solid'in render sisteminin işleri manuel olarak bölmek için ek bir maliyeti yoktur. ```jsx function Deferred(props) { @@ -28,4 +28,4 @@ function Deferred(props) { } ``` -All work in Solid is queued independently already. No need for things like Time Slicing. +Solid'de tüm işlemler bağımsız olarak sıralanır. Time Slicing gibi ek işlere gerek yoktur. diff --git a/langs/tr/tutorials/async_suspense_list/lesson.md b/langs/tr/tutorials/async_suspense_list/lesson.md index ef7a656b..2ae2409f 100644 --- a/langs/tr/tutorials/async_suspense_list/lesson.md +++ b/langs/tr/tutorials/async_suspense_list/lesson.md @@ -1,8 +1,8 @@ -Sometimes you have multiple `Suspense` Components that you want to coordinate. One possible approach is to put everything under a single `Suspense`, but that limits us to a single loading behavior. A single fallback state means that everything always needs to wait until the last thing is loaded. Instead, Solid introduces the `SuspenseList` Component to coordinate that. +Bazen, koordine etmek istediğimiz birden fazla `Suspense` bileşenimiz olabilir. Olası yaklaşımlardan birisi, her şeyi tek bir `Suspense` altında toplamaktır, fakat bu bizi tek bir yükleme davranışı ile sınırlar. Tek bir geri dönüş durumu, her şeyin, her zaman, son şey yüklenene kadar beklemesi gerektiği anlamına gelir. Bunun yerine Solid bunu koordine etmek için `SuspenseList` bileşenini sunar. -Consider having multiple `Suspense` components like our example. If we wrap them with a `SuspenseList` configured with `revealOrder` of `forwards`, they will render in the order they appear in the tree regardless of the order they load. This reduces the page jumping around. You can set `revealOrder` to `backwards` or `together`, which, respectively, reverses the order or waits for all Suspense Components to load. In addition there is a `tail` option that can be set to `hidden` or `collapsed`. This overrides the default behavior of showing all fallbacks with either showing none or showing the next one in the direction set by `revealOrder`. +Örneğimizdeki gibi birden fazla `Suspense` bileşenine sahip olduğunuzu düşünün. Bunları, `revealOrder` ve `forwards` ile yapılandırılmış bir `SuspenseList` ile sararsak, yüklenme sıralarına bakılmaksızın ağaçta göründükleri sırada oluşturulurlar. Bu sayfadaki ileri geri hareketi azaltır. `revealOrder`, `backward` veya `together` değerleri ile ayarlanabilir, bu da sırasıyla sırayı tersine çevirir veya tüm `Suspense` bileşenlerinin yüklenmesini bekler. Ayrıca, `hidden` veya `collapsed` olarak ayarlanabilen bir `tail` seçeneği vardır. Bu, tüm geri dönüşleri gösterme varsayılan davranışını ya hiçbirini göstermeyerek ya da `revealOrder` tarafından belirlenen yönde bir sonrakini gösterecek şekilde geçersiz kılar. -Our example currently is a bit of a mess in terms of loading placeholders. While it loads all the data independently we are often showing multiple placeholders depending on the order data loads in. Let's wrap our `ProfilePage` component's JSX in a ``: +Örneğimiz şu anda placeholder'ların yüklenmesi açısından biraz karışık durumda. Tüm veriler bağımsız olarak yüklenirken verilerin yüklenme sırasına bağlı olarak genellikle birden fazla placeholder gösteriyoruz. `ProfilePage` bileşenimizin JSX'ini bir `` ile saralım. ```jsx diff --git a/langs/tr/tutorials/async_transitions/lesson.md b/langs/tr/tutorials/async_transitions/lesson.md index 19e386f8..b8cd7c3f 100644 --- a/langs/tr/tutorials/async_transitions/lesson.md +++ b/langs/tr/tutorials/async_transitions/lesson.md @@ -1,22 +1,22 @@ -`Suspense` allows us to show fallback content when data is loading. This is great for initial loading, but on subsequent navigation it is often worse UX to fallback to the skeleton state. +`Suspense`, veriler yüklenirken fallback içeriği görmemizi sağlar. Bu durum ilk yükleme için harika olsa da devamındaki gezinmeler için iskelet durumuna geri dönmek genellikle daha kötü bir kullanıcı deneyimi yaşatır. -We can avoid going back to the fallback state by leveraging `useTransition`. It provides a wrapper and a pending indicator. The wrapper puts all downstream updates in a transaction that doesn't commit until all async events complete. +Bu durumlar için `useTransition` kullanabiliriz ve fallback durumuna geri dönmeyi engelleyebiliriz. `useTransition` bir wrapper ve bir pending indicator sağlar. Wrapper, bütün downstream güncellemeleri bütün asenkron event'ler tamamlanana kadar bekleyen bir transaction'a koyar. -This means that when control flow is suspended, it continues to show the current branch while rendering the next off-screen. Resource reads under existing boundaries add it to the transition. However, any new nested `Suspense` components will show "fallback" if they have not completed loading before coming into view. +Bunun anlamı, `useTransition`, kontrol akışı suspend edildiğinde, bir sonraki işlem ekran dışında işlenirken, mevcut durumu görüntülemeye devam eder. Mevcut sınırların içindeki Resource okumaları da transition'a eklenir. Ancak, yeni iç içe geçmiş `Suspense` bileşenleri, görünüme gelmeden önce yüklemeyi tamamlamışlarsa "fallback" göstereceklerdir. -Notice when you navigate in the example, we keep seeing the content disappear back to a loading placeholder. Let's add a transition in our `App` component. First, let's replace the `updateTab` function: +Örnekte gezinirken, içeriğin loading placeholder'ına geri döndüğüne dikkat edin. `App` bileşenimiz için bir transition ekleyelim. İlk olarak `updateTab` fonksiyonunu değiştirelim: ```js const [pending, start] = useTransition(); const updateTab = (index) => () => start(() => setTab(index)); ``` -`useTransition` returns a pending signal indicator and a method to start the transition, which we will wrap around our update. +`useTransition` bir bekleyen sinyal göstergesi (pending signal indicator) ve güncellememizin etrafını saracağımız geçişi başlatmak üzere bir metot döndürür. -We should use that pending signal to give an indicator in our UI. We can add a pending class to our tab container div: +Bu bekleyen sinyali kullanıcı arayüzünde bir bilgilendirme oluşturacak şekilde kullanmalıyız. `tab` container `div`'ine bir pending sınıfı ekleyebiliriz: ```js
    ``` -And with that our tab switching should be much smoother. +Bu şekilde sekme geçişlerimiz çok daha akıcı olacaktır. From abe1eebfa17f80459bd6daf095d1d9b53fea7765 Mon Sep 17 00:00:00 2001 From: Wralith Date: Sat, 22 Oct 2022 01:16:21 +0300 Subject: [PATCH 17/17] docs(tr): update async_lazy More clear and natural explanation --- langs/tr/tutorials/async_lazy/lesson.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/langs/tr/tutorials/async_lazy/lesson.md b/langs/tr/tutorials/async_lazy/lesson.md index 2eaf565b..d23ac4a0 100644 --- a/langs/tr/tutorials/async_lazy/lesson.md +++ b/langs/tr/tutorials/async_lazy/lesson.md @@ -1,4 +1,4 @@ -Bütün bundler'lar (Webpack, Rollup, Parcel, Vite) dinamik import'lar kullandığından kod bölme (code splitting) işlemini otomatik olarak gerçekleştirir. Solid'in lazy metodu, ertelenmiş lazy yükleme için bileşenin dinamik import'unu wrap etmenizi sağlar. Çıktı, JSX'te normal bir şekilde kullanılabilen bileşendir ve tek fark ilk kez render edilişinde import ettiği kodu dinamik olarak yüklemesi ve kod elde edilene kadar render branch'ını durdurmasıdır. +Bütün bundler'lar (Webpack, Rollup, Parcel, Vite vb.) dinamik import'lar kullandığından, kod bölme (code splitting) işlemini otomatik olarak gerçekleştirirler. Solid'in içerisindeki `lazy` metodu, ertelenmiş lazy yükleme için, bileşenin dinamik import'unu wrap etmenizi sağlar. Çıktı, JSX'te normal bir şekilde kullanılabilen bir bileşenden farksızdır ancak tek fark `lazy` ile oluşturulan import ilk kez render edildiğinde, import ettiği kodu dinamik olarak yükler ve kod elde edilene kadar o render kolunu durdurur. `lazy` kullanmak için aşağıdaki satırı: ```js @@ -9,7 +9,7 @@ Aşağıdaki ile değiştirelim: const Greeting = lazy(() => import("./greeting")); ``` -Büyük olasılıkla hala gözle fark edilemeyecek kadar hızlı olacaktır, fakat yüklenmeyi görmek isterseniz bir miktar sahte gecikme ekleyebilirsiniz. +İşlem büyük olasılıkla hala gözle fark edilemeyecek kadar hızlı olacaktır, eğer yüklenmeyi görmek isterseniz bir miktar sahte gecikme ekleyebilirsiniz. ```js const Greeting = lazy(async () => {