I specialize in developing product, design patterns and large zero-to-one SASS projects.

As a frontend developer, I have 4 years of experience solving complex frontend and interface challenges. To build better and great companies, I can offer you my soft engineering skills, previous experiences and with my best practises that I gain from Startup and Big Company projects. And I am trying to improve my cloud skill with AWS and microservices with Node.js nowadays.

I currently live in Istanbul / Turkey, where you can find me chatting about the Middle-Earth, camping in ROHAN, strolling through the SHIRE meadows, drinking in BREE or wandering through the forests of LOTHLORIEN. ­čĆö ­čŹü ­čĆé

React QueryÔÇŐÔÇöÔÇŐYou do not need a Global State Manager
<h3>React QueryÔÇŐÔÇöÔÇŐYou do not need a Global State┬áManager</h3> <figure><img alt="" src="*dnFeqbKCI3OlAKjLNb4Gqg.png"></figure><p>Today I wonÔÇÖt give you something that you canÔÇÖt find in the documentation of <a href="">@tanstack</a>/react-query. So you can find more detail on the documentation. IÔÇÖll give you most use cases with examples and some of my experience with <a href="">@tanstack</a>/react-query.</p> <p>What is React Query in a nutshell?</p> <ul> <li>2 hooks + 1┬áutility</li> <li>5 kb</li> <li>ready-to-use</li> <li>highly configurable</li> </ul> <p>You can use <a href="">@tanstack</a>/react-query and your global state management together. And with <a href="">@tanstack</a>/react-query you can fetch, cache, and update data in your React and React Native applications all without touching any ÔÇťglobal stateÔÇŁ. So time to replace some of your state management logic with <a href="">@tanstack</a>/react-query.</p> <p>Why should you use <a href="">@tanstack</a>/react-query in your┬áproject?</p> <ul> <li>You canÔÇÖt mess it up. Yes if you use global state management and you donÔÇÖt have enough experiences in react you can easily knot your project. But with react-query, you canÔÇÖt do that even if you want it┬á:)</li> <li>It gives us the power of best practices of fetching with its own states, (like isLoading, isError, error,┬áetcÔÇŽ)</li> <li>Powerful cache and stale┬ásystem.</li> <li>Provide shorter codes. So at the end of the day, you will delete lots of line codes in your codebase.</li> </ul> <p>I wanna show my notes on react-query. So letÔÇÖs look at some key use┬ácases.</p> <h3>Installation</h3> <pre>yarn add @tanstack/react-query @tanstack/react-query/devtools axios</pre> <h3>Setup</h3> <ul> <li>I will go with a next app. And you can also use a free API. (<a href=""></a>)</li> <li>You should import QueryClientProvider, and QueryClient to your main App file and wrap your component with QueryClientProvider like┬ábelow.</li> <li>Then you should create a queryClient with QueryClient like below and you should give this queryClient to QueryClientProvider.</li> <li>And to see dev tools we should import ReactQueryDevtools and write it inside the QueryClientProvider. And set it in a position to see┬áit.</li> </ul> <pre>import '../styles/globals.css'<br>import type {AppProps} from 'next/app'<br>import {QueryClientProvider, QueryClient} from '@tanstack/react-query'<br>import {ReactQueryDevtools} from '@tanstack/react-query/devtools'</pre> <pre>function MyApp({Component, pageProps}: AppProps) {<br> const queryClient = new QueryClient()</pre> <pre> return (<br> &lt;QueryClientProvider {...pageProps} client={queryClient}&gt;<br> &lt;Component {...pageProps} /&gt;<br> &lt;ReactQueryDevtools initialIsOpen={false} position="bottom-right" /&gt;<br> &lt;/QueryClientProvider&gt;<br> )<br>}<br>export default MyApp</pre> <h3>APIs</h3> <h3>useQuery</h3> <h3>Basic Fetch</h3> <p>We can use useQuery hook to fetch datas like below. it will return us lots of things. Like data, isLoading, error.</p> <pre>import type {NextPage} from 'next'<br>import {useQuery} from '@tanstack/react-query'<br>import Link from 'next/link'<br>import axios from 'axios'</pre> <pre>const Home: NextPage = () =&gt; {<br> const {data, isLoading, error} = useQuery(<br> ['users',]<br> async () =&gt; {<br> return await axios.get('http://localhost:4000/users')<br> },<br> )</pre> <pre> return (<br> &lt;div&gt;<br> {isLoading &amp;&amp; &lt;&gt;Loading...&lt;/&gt;}<br> {error &amp;&amp; &lt;&gt;Error: {error.message}&lt;/&gt;}<br> {data? =&gt; (<br> &lt;p key={}&gt;{}&lt;/p&gt;<br> ))}<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default Home</pre> <h3>Advanced Fetch</h3> <h4>isFetching</h4> <p>You can see the fetching moment by isFetching like┬ábelow.</p> <h4>refetch</h4> <p>Or you can refetch with your action. You can give this utility to a onClick or anything that you want to trigger┬áby.</p> <pre>import type {NextPage} from 'next'<br>import {useQuery} from '@tanstack/react-query'<br>import Link from 'next/link'<br>import axios from 'axios'</pre> <pre>const Home: NextPage = () =&gt; {<br> const {data, isLoading, error, isFetching, refetch} = useQuery(<br> ['users'],<br> async () =&gt; {<br> return await axios.get('http://localhost:4000/users')<br> }<br> )</pre> <pre> return (<br> &lt;div&gt;<br> &lt;nav&gt;<br> &lt;Link href={`/`}&gt;Home&lt;/Link&gt;<br> &lt;Link href={`/users`}&gt;Users&lt;/Link&gt;<br> &lt;Link href={`/users-rq`}&gt;Users-RQ&lt;/Link&gt;<br> &lt;Link href={`/users-rq-ssr`}&gt;Users-RQ-SSR&lt;/Link&gt;<br> &lt;/nav&gt;</pre> <pre> &lt;div&gt;<br> {isLoading &amp;&amp; &lt;&gt;Loading...&lt;/&gt;}<br> {isFetching &amp;&amp; &lt;&gt;Fetching...&lt;/&gt;}<br> {error &amp;&amp; &lt;&gt;Error: {error.message}&lt;/&gt;}<br> {data? =&gt; (<br> &lt;p key={}&gt;{}&lt;/p&gt;<br> ))}<br> &lt;button onClick={refetch}&gt;Fetch Users&lt;/button&gt;<br> &lt;/div&gt;<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default Home</pre> <h4>Info About┬áTimes</h4> <p>1000 =&gt; 1 second 5000 =&gt; 5 seconds 5000000 =&gt; 5┬áminutes</p> <h4>cacheTime</h4> <p>default =&gt; 5000000 / 5 minutes It will cache the data for 5 seconds if you write 5000 like┬áme.</p> <h4>staleTime</h4> <p>default =&gt; 0 / 0 seconds Your data that you fetch will be stale data after 4┬áseconds</p> <h4>refetchOnMount</h4> <p>default =&gt; true other options =&gt; ÔÇťalwaysÔÇŁ |┬áfalse</p> <h4>refetchOnWindowFocus</h4> <p>default =&gt; true other options =&gt; ÔÇťalwaysÔÇŁ | false Focus = We are doing something outside of the browser or outside of our app tab then we are returning to our app tab. This will fetch the data again if you focus your app again. For example, if you open another app or another tab then if you come back to your app page, it will fetch the data┬áagain.</p> <pre>import type {NextPage} from 'next'<br>import {useQuery} from '@tanstack/react-query'<br>import Link from 'next/link'<br>import axios from 'axios'</pre> <pre>const Home: NextPage = () =&gt; {<br> const {data, isLoading, error, isFetching, refetch} = useQuery(<br> ['users'],<br> async () =&gt; {<br> return await axios.get('http://localhost:4000/users')<br> },<br> {<br> cacheTime: 5000,<br> staleTime: 4000,<br> refetchOnMount: true,<br> refetchOnWindowFocus: true<br> },<br> )</pre> <pre> return (<br> &lt;div&gt;<br> &lt;nav&gt;<br> &lt;Link href={`/`}&gt;Home&lt;/Link&gt;<br> &lt;Link href={`/users`}&gt;Users&lt;/Link&gt;<br> &lt;Link href={`/users-rq`}&gt;Users-RQ&lt;/Link&gt;<br> &lt;Link href={`/users-rq-ssr`}&gt;Users-RQ-SSR&lt;/Link&gt;<br> &lt;/nav&gt;</pre> <pre> &lt;div&gt;<br> {isLoading &amp;&amp; &lt;&gt;Loading...&lt;/&gt;}<br> {isFetching &amp;&amp; &lt;&gt;Fetching...&lt;/&gt;}<br> {error &amp;&amp; &lt;&gt;Error: {error.message}&lt;/&gt;}<br> {data? =&gt; (<br> &lt;p key={}&gt;{}&lt;/p&gt;<br> ))}<br> &lt;button onClick={refetch}&gt;Fetch Users&lt;/button&gt;<br> &lt;/div&gt;<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default Home</pre> <h4>refetchOnWindowFocus and staleTime</h4> <pre>staleTime: 10000,<br>refetchOnWindowFocus: true,</pre> <p>If we use this together and if the data is not stale, we will not fetch data again, even if we pass refetchOnWindowFocus: true. <em>refetchOnWindowFocus</em> will fetch if your data is a staled┬ádata.</p> <p>Of course you can get over this problem if you need. Just pass ÔÇťalwaysÔÇŁ as value. like┬ábelowÔÇŽ</p> <pre>staleTime: 10000,<br>refetchOnWindowFocus: "always",</pre> <h4>refetchInterval (Polling)</h4> <p>default =&gt; false This will fetch data on every timespan which you wrote┬ábelow.</p> <h4>refetchIntervalInBackground</h4> <p>default =&gt; false This will fetch data even if your focus is not on your app tab or browser┬áeither</p> <pre>import type {NextPage} from 'next'<br>import {useQuery} from '@tanstack/react-query'<br>import Link from 'next/link'<br>import axios from 'axios'</pre> <pre>const Home: NextPage = () =&gt; {<br> const {data, isLoading, error, isFetching, refetch} = useQuery(<br> ['users'],<br> async () =&gt; {<br> return await axios.get('http://localhost:4000/users')<br> },<br> {<br> refetchInterval: 2000,<br> refetchIntervalInBackground: true,<br> },<br> )</pre> <pre> return (<br> &lt;div&gt;<br> &lt;nav&gt;<br> &lt;Link href={`/`}&gt;Home&lt;/Link&gt;<br> &lt;Link href={`/users`}&gt;Users&lt;/Link&gt;<br> &lt;Link href={`/users-rq`}&gt;Users-RQ&lt;/Link&gt;<br> &lt;Link href={`/users-rq-ssr`}&gt;Users-RQ-SSR&lt;/Link&gt;<br> &lt;/nav&gt;</pre> <pre> &lt;div&gt;<br> {isLoading &amp;&amp; &lt;&gt;Loading...&lt;/&gt;}<br> {isFetching &amp;&amp; &lt;&gt;Fetching...&lt;/&gt;}<br> {error &amp;&amp; &lt;&gt;Error: {error.message}&lt;/&gt;}<br> {data? =&gt; (<br> &lt;p key={}&gt;{}&lt;/p&gt;<br> ))}<br> &lt;button onClick={refetch}&gt;Fetch Users&lt;/button&gt;<br> &lt;/div&gt;<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default Home</pre> <h4>onSuccess &amp;┬áonError</h4> <p>You can pass a callback function for onSuccess and onError. Also if the fetching is successful you will get the data if it has an error you will get the┬áerror.</p> <h4>select</h4> <p>You can use select to modify your return data. As you see below before I was using but after select, I can use just┬á</p> <pre>import type {NextPage} from 'next'<br>import {useQuery} from '@tanstack/react-query'<br>import Link from 'next/link'<br>import axios from 'axios'</pre> <pre>const Home: NextPage = () =&gt; {<br> const onSuccess = data =&gt; {<br> console.log("You've got data: ", data)<br> }</pre> <pre> const onError = error =&gt; {<br> console.log("You've got an error: ", error)<br> }</pre> <pre> const {data, isLoading, error, isFetching, refetch} = useQuery(<br> ['users'],<br> async () =&gt; {<br> return await axios.get('http://localhost:4000/users')<br> },<br> {<br> onSuccess,<br> onError,<br> select: data =&gt;,<br> },<br> )</pre> <pre> return (<br> &lt;div&gt;<br> &lt;nav&gt;<br> &lt;Link href={`/`}&gt;Home&lt;/Link&gt;<br> &lt;Link href={`/users`}&gt;Users&lt;/Link&gt;<br> &lt;Link href={`/users-rq`}&gt;Users-RQ&lt;/Link&gt;<br> &lt;Link href={`/users-rq-ssr`}&gt;Users-RQ-SSR&lt;/Link&gt;<br> &lt;/nav&gt;</pre> <pre> &lt;div&gt;<br> {isLoading &amp;&amp; &lt;&gt;Loading...&lt;/&gt;}<br> {isFetching &amp;&amp; &lt;&gt;Fetching...&lt;/&gt;}<br> {error &amp;&amp; &lt;&gt;Error: {error.message}&lt;/&gt;}<br> {/* before select =&gt; {data? =&gt; ( */}<br> {data?.map(item =&gt; (<br> &lt;p key={}&gt;{}&lt;/p&gt;<br> ))}<br> &lt;button onClick={refetch}&gt;Fetch Users&lt;/button&gt;<br> &lt;/div&gt;<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default Home</pre> <h4>Multiple Places with the Same┬áuseQuery</h4> <p>If you need to use the same useQuery multiple components or multiple pages, you can create a utility with the same useQuery logic and you can use it anywhere you┬áwant.</p> <p><em>/hooks/useUsersData.js</em></p> <pre>import {useQuery} from '@tanstack/react-query'<br>import axios from 'axios'</pre> <pre>export const useUsersData = ({config}) =&gt; {<br> return useQuery(<br> ['users'],<br> async () =&gt; {<br> return await axios.get('http://localhost:4000/users')<br> },<br> {<br> ...config,<br> },<br> )<br>}</pre> <p><em>/pages/xxx.js</em></p> <pre>import type {NextPage} from 'next'<br>import Link from 'next/link'<br>import {useUsersData} from '../../src/hooks'</pre> <pre>const Home: NextPage = () =&gt; {<br> const onSuccess = data =&gt; {<br> console.log("You've got data: ", data)<br> }</pre> <pre> const onError = error =&gt; {<br> console.log("You've got an error: ", error)<br> }</pre> <pre> const {data, isLoading, error, isFetching, refetch} = useUsersData({<br> onSuccess,<br> onError,<br> select: data =&gt;,<br> })</pre> <pre> return (<br> &lt;div&gt;<br> &lt;nav&gt;<br> &lt;Link href={`/`}&gt;Home&lt;/Link&gt;<br> &lt;Link href={`/users`}&gt;Users&lt;/Link&gt;<br> &lt;Link href={`/users-rq`}&gt;Users-RQ&lt;/Link&gt;<br> &lt;Link href={`/users-rq-ssr`}&gt;Users-RQ-SSR&lt;/Link&gt;<br> &lt;/nav&gt;</pre> <pre> &lt;div&gt;<br> {isLoading &amp;&amp; &lt;&gt;Loading...&lt;/&gt;}<br> {isFetching &amp;&amp; &lt;&gt;Fetching...&lt;/&gt;}<br> {error &amp;&amp; &lt;&gt;Error: {error.message}&lt;/&gt;}<br> {/* before select =&gt; {data? =&gt; ( */}<br> {data?.map(item =&gt; (<br> &lt;p key={}&gt;{}&lt;/p&gt;<br> ))}<br> &lt;button onClick={refetch}&gt;Fetch Users&lt;/button&gt;<br> &lt;/div&gt;<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default Home</pre> <h4>How useQuery cache in Dynamic Pages like /users/1, /users/2</h4> <p>As you know when we create [id].js file in next js for dynamic pages. It is similar in pure react too. So the page is the same file. So how can useQuery understand the previous cache is from /1 or /2. We will see how <a href="">@tanstack</a>/react-query handle this with useQuery.</p> <p>First letÔÇÖs create a dynamic page under the /users <em>/pages/users/[id].js</em></p> <pre>import type {NextPage} from 'next'<br>import {useQuery} from '@tanstack/react-query'<br>import Link from 'next/link'<br>import axios from 'axios'<br>import {useUsersData} from '../../src/hooks'<br>import {useRouter} from 'next/router'</pre> <pre>const Users: NextPage = () =&gt; {<br> const router = useRouter()</pre> <pre> const {id} = router.query</pre> <pre> const {data, isLoading, error} = useUsersData(id, {<br> select: data =&gt;,<br> })</pre> <pre> return (<br> &lt;div&gt;<br> &lt;nav&gt;<br> &lt;Link href={`/`}&gt;Home&lt;/Link&gt;<br> &lt;Link href={`/users`}&gt;Users&lt;/Link&gt;<br> &lt;Link href={`/users-rq`}&gt;Users-RQ&lt;/Link&gt;<br> &lt;Link href={`/users-rq-ssr`}&gt;Users-RQ-SSR&lt;/Link&gt;<br> &lt;/nav&gt;</pre> <pre> &lt;div&gt;<br> {isLoading &amp;&amp; &lt;&gt;Loading...&lt;/&gt;}<br> {error &amp;&amp; &lt;&gt;Error: {error.message}&lt;/&gt;}<br> &lt;div&gt;Id: {id}&lt;/div&gt;<br> &lt;div&gt;Name: {data?.name}&lt;/div&gt;<br> &lt;div&gt;Alter Ego: {data?.alterEgo}&lt;/div&gt;<br> &lt;/div&gt;<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default Users</pre> <p>Now letÔÇÖs create our useQuery hooks. As you see below we pass an array as its first argument. one is ÔÇśusersÔÇÖ the second one is a dynamic value. In this way, <a href="">@tanstack</a>/react-query understands cache correctly. If we donÔÇÖt do this and if we pass just ÔÇśusersÔÇÖ instead of an array, then when we open /users/1 <a href="">@tanstack</a>/react-query will cache this, then when we open /users/2, <a href="">@tanstack</a>/react-query will show use the cache of /users/1. So it is an unwanted side-effect that we donÔÇÖt want. So we can handle it like┬ábelow.</p> <pre>import {useQuery} from '@tanstack/react-query'<br>import axios from 'axios'</pre> <pre>export const useUsersData = (userId, config) =&gt; {<br> return useQuery(<br> ['users', userId],<br> async () =&gt; {<br> return await axios.get(`http://localhost:4000/users/${userId}`)<br> },<br> {<br> ...config,<br> },<br> )<br>}</pre> <p>Or we can handle it like below with queryKey.</p> <pre>const fetchUsers = async ({queryKey}) =&gt; {<br> // queryKey === ['users', userId]<br> const userId = queryKey[1]</pre> <pre> return await axios.get(`http://localhost:4000/users/${userId}`)<br>}</pre> <pre>export const useUsersDataWithQueryKey = (userId, config) =&gt; {<br> return useQuery(['users', userId], fetchUsers, {<br> ...config,<br> })<br>}</pre> <h4>Dynamic Multiple┬áRequests</h4> <p>Or we can fetch multiple requests as dynamic. Ex: with props like┬ábelow</p> <pre>import type {NextPage} from 'next'<br>import {useQueries} from '@tanstack/react-query'<br>import axios from 'axios'</pre> <pre>const fetchUser = async (id: string) =&gt; {<br> return await axios.get(`http://localhost:4000/users/${id}`)<br>}</pre> <pre>const DynamicParallelQueries: NextPage = ({userIds = [1, 3]}) =&gt; {<br> const [{data: userOne}, {data: userThree}] = useQueries(<br> =&gt; ({<br> queryKey: ['user', id],<br> queryFn: async () =&gt; fetchUser(id),<br> })),<br> )</pre> <pre> return (<br> &lt;div&gt;<br> &lt;p&gt;Users&lt;/p&gt;<br> &lt;p&gt;UserOne Name: {userOne?.data.username}&lt;/p&gt;<br> &lt;p&gt;UserThree Name: {userThree?.data.username}&lt;/p&gt;<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default DynamicParallelQueries</pre> <h4>Dependent Query┬áFetching</h4> <p>As you can see below we can fetch dependent query fetching together. We can wait request with useQuery thanks to┬áenabled.</p> <pre>import type {NextPage} from 'next'<br>import {useQuery} from '@tanstack/react-query'<br>import Link from 'next/link'<br>import axios from 'axios'</pre> <pre>const fetchUserByEmail = async (email: string) =&gt; {<br> return await axios.get(`http://localhost:4000/users/${email}`)<br>}</pre> <pre>const fetchCoursesByEmail = async () =&gt; {<br> return await axios.get(`http://localhost:4000/courses`)<br>}</pre> <pre>const DependentQueries: NextPage = ({email = ''}) =&gt; {<br> const {data: userData} = useQuery(['user', email], () =&gt;<br> fetchUserByEmail(email),<br> )<br> const user = userData?.data<br> const userId = user?.id</pre> <pre> const {data: coursesData} = useQuery(<br> ['courses', userId],<br> () =&gt; fetchCoursesByEmail(),<br> {<br> enabled: !!userId,<br> select: data =&gt;<br> data?.data?.filter(course =&gt; === user?.username),<br> },<br> )<br></pre> <pre> return (<br> &lt;div&gt;<br> &lt;div&gt;<br> &lt;p&gt;User Id: {userId}&lt;/p&gt;<br> {email}</pre> <pre> &lt;p&gt;Courses&lt;/p&gt;<br> {coursesData?.map(item =&gt; (<br> &lt;div key={}&gt;<br> &lt;p&gt;Author: {}&lt;/p&gt;<br> &lt;p&gt;{item.title}&lt;/p&gt;<br> &lt;/div&gt;<br> ))}<br> &lt;/div&gt;<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default DependentQueries</pre> <h4>useQueryClient().getQueryData &amp; initialData</h4> <p>useQueryClient =&gt; we can create a query client with useQueryClient hook. And we can use its getQueryData to get the data that it fetched before. initialData =&gt; we can use initialData key to return an initial value with useQuery┬áhooks.</p> <p>In this example, we send a request to get all users before this request below which is ÔÇťusersÔÇŁ. Then we click one of the users to see its detail and we send another useQuery with ÔÇťuserÔÇŁ key. But we donÔÇÖt want to see loading, we want to see data instead of that. Then we can use ÔÇťgetQueryDataÔÇŁ of queryClient. like┬ábelow.</p> <pre>import {useQuery, useQueryClient} from '@tanstack/react-query'<br>import axios from 'axios'</pre> <pre>export const useUserData = (userId, config) =&gt; {<br> const queryClient = useQueryClient()</pre> <pre> return useQuery(<br> ['user', userId],<br> async () =&gt; {<br> return await axios.get(`http://localhost:4000/users/${userId}`)<br> },<br> {<br> ...config,<br> initialData: () =&gt; {<br> const user = queryClient<br> .getQueryData('users')<br> ?.data?.find(item =&gt; == userId)</pre> <pre> if (user) {<br> return {<br> data: user,<br> }<br> } else {<br> return undefined<br> }<br> },<br> },<br> )<br>}</pre> <h4>Pagination &amp; keepPreviousData and Avoiding Layout┬áShift</h4> <p>Pagination is as simple as below. We just keep a state to know page number and increment and decrement it. I wrote hardcoded it but you can get it from your database dynamically.</p> <h4>keepPreviousData</h4> <p>default =&gt; false we can use ÔÇťkeepPreviousDataÔÇŁ key using old data. We can avoid layout shifting thanks to ÔÇťkeepPreviousDataÔÇŁ. We just need to turn on ÔÇťkeepPreviousDataÔÇŁ to true. And by this way, we will keep and show previous data until we fetch the new data on the page. For example below we fetch the first page and we show 3 colors on 1. page. But when we click next we will still show the first page items until we fetch the items of the 2.┬ápage.</p> <pre>import type {NextPage} from 'next'<br>import {useQuery} from '@tanstack/react-query'<br>import axios from 'axios'<br>import {useState} from 'react'</pre> <pre>const PaginatedQueries: NextPage = () =&gt; {<br> const [page, setPage] = useState(1)<br> const {data, isLoading, isError, error} = useQuery(<br> ['colors', page],<br> async () =&gt; {<br> return await axios.get(<br> `http://localhost:4000/colors?_limit=3&amp;_page=${page}`,<br> )<br> },<br> {<br> keepPreviousData: true,<br> },<br> )</pre> <pre> if (isLoading) {<br> return &lt;&gt;Loading...&lt;/&gt;<br> }<br> if (isError) {<br> return &lt;&gt;Error: {error?.message}&lt;/&gt;<br> }</pre> <pre> return (<br> &lt;div&gt;<br> &lt;p&gt;Colors&lt;/p&gt;<br> {data? =&gt; (<br> &lt;p key={}&gt;{item.label}&lt;/p&gt;<br> ))}<br> &lt;button onClick={() =&gt; setPage(prev =&gt; prev - 1)} disabled={page &lt; 2}&gt;<br> Prev<br> &lt;/button&gt;<br> &lt;button onClick={() =&gt; setPage(prev =&gt; prev + 1)} disabled={page &gt; 2}&gt;<br> Next<br> &lt;/button&gt;<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default PaginatedQueries</pre> <h4>useInfiniteQuery &amp; hasNextPage &amp; fetchNextPage</h4> <p>useInfiniteQuery =&gt; We can use ÔÇťuseInfiniteQueryÔÇŁ to implement and fetch infinite loading to our page. fetchNextPage =&gt; When we use this hook we can also use ÔÇťfetchNextPageÔÇŁ to trigger the load more button. hasNextPage =&gt; ÔÇťhasNextPageÔÇŁ will give us that we have a next page or not. We will return its return with ÔÇťgetNextPageParamÔÇŁ option.</p> <pre>import type {NextPage} from 'next'<br>import {useInfiniteQuery} from '@tanstack/react-query'<br>import axios from 'axios'</pre> <pre>const fetchColors = async ({pageParam = 1}) =&gt; {<br> // pageParam =&gt; 1, 2, 3, ...<br> return await axios.get(<br> `http://localhost:4000/colors?_limit=3&amp;_page=${pageParam}`,<br> )<br>}</pre> <pre>const InfiniteQueries: NextPage = () =&gt; {<br> const {data, isLoading, isError, error, hasNextPage, fetchNextPage} =<br> useInfiniteQuery(['colors'], fetchColors, {<br> getNextPageParam: (_lastPage, pages) =&gt; {<br> if (pages.length &lt; 3) {<br> return pages.length + 1<br> } else {<br> return undefined<br> }<br> },<br> })</pre> <pre> if (isLoading) {<br> return &lt;&gt;Loading...&lt;/&gt;<br> }<br> if (isError) {<br> return &lt;&gt;Error: {error?.message}&lt;/&gt;<br> }</pre> <pre> return (<br> &lt;div&gt;<br> &lt;p&gt;Colors&lt;/p&gt;<br> {data?, index) =&gt; (<br> &lt;p key={index}&gt;<br> { =&gt; (<br> &lt;div key={}&gt;{item.label}&lt;/div&gt;<br> ))}<br> &lt;/p&gt;<br> ))}<br> &lt;button onClick={fetchNextPage} disabled={!hasNextPage}&gt;<br> show more<br> &lt;/button&gt;<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default InfiniteQueries</pre> <h3>useMutation</h3> <h3>mutate &amp; POST┬áRequests</h3> <p>We can use mutate for post requests and we can use them like┬ábelow.</p> <h4>queryClient.invalidateQueries</h4> <p>We can mark the query as stale and we can tell it should be re-fetched again. So below when we add a user with useMutation hook then we can create a ÔÇťqueryClientÔÇŁ and use ÔÇťinvalidateQueriesÔÇŁ method inside of its onSuccess case. We can call it and we can say the usersÔÇÖ data is stale you should re-fetch┬áit.</p> <pre>import axios from 'axios'<br>import type {NextPage} from 'next'<br>import Link from 'next/link'<br>import {useEffect, useState} from 'react'<br>import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'</pre> <pre>const Home: NextPage = () =&gt; {<br> const [email, setEmail] = useState()<br> const [password, setPassword] = useState()</pre> <pre> const {<br> data: usersData,<br> isLoading,<br> isError,<br> error,<br> refetch,<br> } = useQuery(['users'], async () =&gt; {<br> return await axios.get('http://localhost:4000/users')<br> })</pre> <pre> const addUser = async user =&gt; {<br> return'http://localhost:4000/users', user)<br> }</pre> <pre> const queryClient = useQueryClient()<br> const {<br> mutate,<br> isError: mutateIsError,<br> error: mutateError,<br> isLoading: mutateIsLoading,<br> } = useMutation(addUser, {<br> onSuccess: () =&gt; {<br> queryClient.invalidateQueries('users')<br> },<br> })</pre> <pre> const handleAddUserClick = () =&gt; {<br> const user = {<br> email,<br> password,<br> }<br> mutate(user)<br> }</pre> <pre> if (isLoading) return &lt;&gt;Loading...&lt;/&gt;<br> if (isError) return &lt;&gt;Error: {error.message}&lt;/&gt;</pre> <pre> return (<br> &lt;div&gt;<br> &lt;nav&gt;<br> &lt;Link href={`/`}&gt;Home&lt;/Link&gt;<br> &lt;Link href={`/users`}&gt;Users&lt;/Link&gt;<br> &lt;Link href={`/users-rq`}&gt;Users-RQ&lt;/Link&gt;<br> &lt;Link href={`/users-rq-ssr`}&gt;Users-RQ-SSR&lt;/Link&gt;<br> &lt;/nav&gt;<br> &lt;div&gt;<br> &lt;div&gt;<br> &lt;input<br> type="text"<br> value={email}<br> onChange={e =&gt; setEmail(}<br> /&gt;<br> &lt;input<br> type="text"<br> value={password}<br> onChange={e =&gt; setPassword(}<br> /&gt;<br> &lt;button onClick={handleAddUserClick}&gt;Add User&lt;/button&gt;<br> &lt;/div&gt;<br> {usersData?.data?.map(item =&gt; (<br> &lt;p key={}&gt;{}&lt;/p&gt;<br> ))}<br> &lt;button onClick={refetch}&gt;Refetch&lt;/button&gt;<br> &lt;/div&gt;<br> &lt;/div&gt;<br> )<br>}</pre> <pre>export default Home</pre> <h4>setQueryData</h4> <p>Instead of using ÔÇťinvalidateQueriesÔÇŁ like above, we can use ÔÇťsetQueryDataÔÇŁ to get updated data. with ÔÇťinvalidateQueriesÔÇŁ we can send a new fetch request and get updated data again. Instead of this we can use ÔÇťsetQueryDataÔÇŁ and manipulate the ÔÇťqueryÔÇŁ of ÔÇťusersÔÇŁ. In this way, we do not need to send an extra one more request to get new┬ádata.</p> <pre> onSuccess: data =&gt; {<br> // queryClient.invalidateQueries('users')<br> queryClient.setQueryData('users', oldQueryData =&gt; {<br> return {<br> ...oldQueryData,<br> data: [,],<br> }<br> })<br> }</pre> <h4>refetchQueries</h4> <p>Or if we need to fetch these data from more than one place, then we need to fetch the data for all of them. So we can use ÔÇťrefetchQueriesÔÇŁ to update them┬áall.</p> <pre> onSuccess: data =&gt; {<br> // queryClient.invalidateQueries('users')<br> // queryClient.setQueryData('users', oldQueryData =&gt; {<br> // return {<br> // ...oldQueryData,<br> // data: [,],<br> // }<br> // })<br> queryClient.refetchQueries("users")<br> }</pre> <h4>Optimistic Updates</h4> <p>Source =&gt; <a href=""></a></p> <ul> <li>We can immediately update the user interface with new data. (with this =&gt; queryClient.setQueryData(ÔÇśusersÔÇÖ, old =&gt; [ÔÇŽold, newUser]))</li> <li>Then we can send our request, if we have an error we can get back the new data from UI and show the previous data. (with onError =&gt; queryClient.setQueryData(ÔÇśusersÔÇÖ, context.previousUsers))</li> <li>And we always re-fetch if the request succeeds or┬áfails.</li> </ul> <p>And these steps give us an optimistic update.</p> <pre>const queryClient = useQueryClient()<br> const {<br> mutate,<br> isError: mutateIsError,<br> error: mutateError,<br> isLoading: mutateIsLoading,<br> } = useMutation(newUser, {<br> //! onMutate =&gt; runs before the mutation is sent to the server<br> onMutate: async newUser =&gt; {<br> // we will cancel the queries because of we dont want they overwrite us<br> // Cancel any outgoing refetches (so they don't overwrite our optimistic update)<br> await queryClient.cancelQueries('users')</pre> <pre> // Snapshot the previous value<br> const previousUsers = queryClient.getQueryData('users')</pre> <pre> // Optimistically update to the new value<br> queryClient.setQueryData('users', old =&gt; [...old, newUser])</pre> <pre> // Return a context object with the snapshotted value<br> return {previousUsers}<br> },</pre> <pre> // If the mutation fails, use the context returned from onMutate to roll back<br> onError: (_error, _user, context) =&gt; {<br> queryClient.setQueryData('users', context.previousUsers)<br> },</pre> <pre> // Always refetch after error or success:<br> onSettled: () =&gt; {<br> queryClient.invalidateQueries('users')<br> },<br> })</pre> <img src=";referrerSource=full_rss&amp;postId=8ed08a7242b" width="1" height="1" alt="">
<figure><img alt="" src="*2bBocWww9Z56Jww-DDpdaA.png"></figure><p>Hi, guys again. In my previous post, I had talked about ÔÇťWritingÔÇŁ and why ÔÇťWritingÔÇŁ matter. Now I want to talk about ÔÇťDOCUMENTATIONÔÇŁ and why it matter. I will give you examples and end of the article I just want you to apply these examples to your organization or projects. And before starting to read this article I suggest you read my previous article which is ÔÇť<a href="">WRITING matter</a>ÔÇŁ. So letÔÇÖs┬ágoÔÇŽ</p> <h4>1. Professionalism</h4> <p>Documenting anything gives and creates professionalism. We can share the story and information by documentation. Teams, companies, organizations and even between companies and customers need to use and share documentation. If you are a tech people you already knew about some API documentation but it is not tech or programmers stuff. Anyone can need documentation in their life or workflow. Think you bought a drawer from IKEA, if there is no installation guide paper inside the box, can you imagine how terrible it is? Yeah that much terrible if we havenÔÇÖt documentation in our jobs and┬álives.</p> <h4>2. Businesses can make much┬ámoney</h4> <p>If you have a business at any scale, you should absolutely keep documentation. And you should set it as a rule for your business. Generally, most small startups do not think and apply these rules. Most of those do not know anything either about documentation. Even they knew they think they donÔÇÖt have time to document. Because they are always in a rush. But they are wrong. They are wasting their money much more than by doing this.┬áWhy?</p> <ul> <li>If your business doesnÔÇÖt document your works, after a while you will investigate and repeat the same works again┬áagain</li> <li>You will spend more money on orientation for a customer or an┬áemployee</li> <li>You will have an unmanageable workflow and it will slow your work┬ádown</li> </ul> <h4>3. Development, Investigation is┬áEasy</h4> <p>It is not only to be more profitable for your company. It increases the quality of your organization and product. You will have a more scalable product. You will have more happy employees. Because everything is organized and ordinary. So everyone is happy to work on the project. No one wants to leave your project. Otherwise, if you had bad documentation,</p> <ul> <li>Your clients, and employees would be unhappy and they would try to leave you at the first┬áchance</li> <li>You can sell your product because it is so bad or you donÔÇÖt have a good documentation</li> <li>If you hadnÔÇÖt documentation you will always depend to the workers who developed your products. If he had some problem then you will be down in a┬ácrisis.</li> </ul> <h4>4. Single source of┬átruth</h4> <p>You can have some disciplines in your organization, if you keep these hot you should keep the documentation for this. Or you can hire people or you can tell and teach by yourself one by one in your organization. Which is simple? I think ÔÇťDocumentationÔÇŁ is simple than doing this. In this way, you can create, define and write your rules and you can want to obey your employees. So your employees will follow the same rules with the same documentation and they will use a single source of truth. I wanna give a general example, Think you have an accountant company and you had 5 accountants, you can set a rule about folder structure and you can want them to obey this rule. So after you get the. report from your accountants you will work faster and effectively and also you wonÔÇÖt try to figure out which files and documents where.</p> <h4>5. Hiring &amp; Onboarding is faster and┬áeasier</h4> <p>If you hire new people to your company they will always need to learn your workflows, styles, and process. So they need to learn these things from somewhere. If you had any documentation then you need to tell them by yourself or you need to hire a person and pay for him. But you donÔÇÖt need to do that. All you need write and document your work at the same time when you have done with a job. Then when you hire a person, or when you sold a product give your documentation link and leave them by themselves. It is such┬áeasy.</p> <h4>6. Cuts down duplication of┬áwork</h4> <p>If you donÔÇÖt have the documentation your jobs and work repeat their selves in time. Because you donÔÇÖt have documentation so your employees will do the same work every time again. Because they can forget the previous job or task, or you can hire a new person who doesnÔÇÖt have any idea about on project. So donÔÇÖt wait and create your document┬ánow.</p> <h3>How you should document┬áit?</h3> <ol> <li>Chose a platform. I strongly recommend you use a cloud note application, such as Notion, confluence or excel, or Google┬áDrive</li> <li>Define the categories and split your organization, piece by piece. <br>(For org: Frontend Team, Backend Team)<br>(For project: Project Name, Project┬áName)</li> <li>Tell the story. Use emojis, colors, white spaces, memes, and┬áimages.</li> <li>Ensure your team, organization or employees contribute this documentation</li> <li>Update the old logic by the time, right┬ánow</li> <li>Create tasks for documentation</li> <li>Write in English because English is the most common language in the┬áworld</li> <li>Keep your documentation simple but it also needs to have more detail inside of it. You can have a level system for┬ádetails.</li> <li>Use clean and sharpen┬átitles</li> <li>DonÔÇÖt write everything, define your requirements and write just what you┬áneed</li> </ol> <h3>Conclusion</h3> <p>I think this is so clear. DonÔÇÖt waste your time, your money, and your employee's time. Start to implement this right now. Create a page and contribute it. I want to share the documentation which I create for my organization. I just want to show you how I organized it and what the folder structures look like. I used confluence to create┬áthis.</p> <figure><img alt="" src="*6jm8GKargyotLRv45QL9BA.png"></figure><p>I also want to share some other documentation of big companies. You can also inspect them and can get some inspiration. So see you next┬átime.</p> <h4>Professional Examples</h4> <ul> <li><a href="">The Workstream | Your One-Stop-Shop for Managing Work</a></li> <li><a href="">React Docs Beta</a></li> </ul> <h3>Sources</h3> <ul> <li><a href="">Importance of Documentation | The Workstream</a></li> <li><a href="">6 Reasons Why Documentation Is Important for Your Investment Operations</a></li> </ul> <h3>Kudos</h3> <p>Also, I can suggest another article which my old colleague wrote before. He also points out lots of important points. I strongly suggest you read this. Kudos to Ezer to share his experiences in this┬áarticle.</p> <p><a href="">How does documentation drive easier organizational scaling?</a></p> <img src=";referrerSource=full_rss&amp;postId=d72f752f5088" width="1" height="1" alt="">
<figure><img alt="" src="*efkv2c_Odjq5X9DqPrwwAA.png"></figure><p>Hi guys. TodayÔÇÖs topic is a really important topic for our business life, career and work life. I want to share this because I believe this is the most important topic in our life. I will tell you why and answer some of the key questions here shortly. But the main job is yours. You should read more articles about this and you should integrate this into yourselves, your teams, or your companies as a life rule. I will put some of the sources below. Then letÔÇÖs┬ástart.</p> <h3>Purposes, reasonsÔÇŽ</h3> <p>There is not just a purpose or reason to write here. There are a lot. As I work and inspect the big companies, they always write something regularly. They write documentation, they write technical blog posts, they write their experiences, they share their codes, and they navigate the people the right way. They always do such things. So they have so much collected experience, and this experience comes from thousands of engineers, decades years. So why donÔÇÖt we follow the steps they experienced and showed┬áus.</p> <p>Okay, I donÔÇÖt wanna make you boring so I will put some of the key purposes of why <strong><em>WRITING</em></strong>┬ámatters.</p> <h4> <strong><em>1. WRITING</em></strong> gives us to create a company┬áculture</h4> <p>Generally, small startups donÔÇÖt think like the big companies and they donÔÇÖt give importance to this topic. So they just trying to push new features. And the most important thing is the income and expense flow of their products. This is wrong. If we create a company culture this will also boost our product quality, our employees' loyalty, happiness in our company, and everything. There are tons of words to write this topic but I donÔÇÖt want to go out of my topic. In a nutshell, if we want to create a company culture, we should write and keep our datas ordinarily.</p> <h4> <strong><em>2. WRITING</em></strong> increases and improves our soft┬áskills</h4> <p>IsnÔÇÖt it so clear? If you write someone will read yours and you will read someoneÔÇÖs datas. And this shared experience improve your soft skill in┬átime.</p> <h4> <strong><em>3. WRITING</em></strong> teaches us new things from each┬áother</h4> <p>The shared datas will teach you new things always. Of course, you can find lots of data on the internet with videos, articles, etcÔÇŽ But in your company, it will be a more real-life experience for you. And if you inspect these datas you will learn and┬áteach.</p> <h4> <strong><em>4. WRITING</em></strong> increases our code qualities</h4> <p>After you learn new things it will reflect your codes and life. You will be writing more clear and more experienced. You will be stronger than ever. I can guarantee this also will reflect your real┬álife.</p> <h4> <strong><em>5. WRITING</em></strong> forces us to apply the single source of the┬átruth</h4> <p>When we develop something we decide to use some tools, and we also follow some best practices. But everyone can apply these things in their own ways. And this is not good. If I give you an example: think you are working in a small team. There are 2 frontend teams. and each team developing their own product. They are using the best practices of the community(usually they donÔÇÖt), and they are using the same tools and languages. But one team is using style.js as a filename, one team is using It is really tiny thing but there is no single source of truth in the company projects. I think this is bad. We should avoid and get rid of these things from our lives. So we should write and force each other to ensure┬áSSoT.</p> <h4> <strong><em>6. WRITING</em></strong> increases our product┬áquality</h4> <p>After the above steps, you will increase your product quality in a visible way. You will realize life how beautiful is.</p> <h4> <strong><em>7. WRITING</em></strong> brings us┬átime</h4> <p>Yes besides all of these things you will get lots of time to yourself, your team, or your company. You wonÔÇÖt waste your time. You will do the job in a good and experienced way. Even if you a nerbie employee you will do your job like a senior employee in the minimum duration.</p> <h4>Where/How to┬ástart?</h4> <p>Choose a tool like Notion, Confluence or something else. And create a structure for your organization. Split into groups your organization and give them some space on there. And create your own datas here and add ordinarily here. Or you can also create a website and share some of these as public to┬ápeople.</p> <h3>Conclusion</h3> <p>There is no end. We can say lots of things about the purposes or reasons for WRITING. And also we donÔÇÖt just write something we should also <strong><em>READ</em></strong>. I put some of the resources below.</p> <p><a href="">Eight Reasons Why Business Writing┬áMatters</a></p> <p><a href="">Why writing matters in the workplace</a></p> <p><a href="">Why Writing MattersÔÇŐÔÇöÔÇŐElectrical &amp; Computer EngineeringÔÇŐÔÇöÔÇŐSaginaw Valley State University</a></p> <p><a href="">CommunicationÔÇŐÔÇöÔÇŐWhy Writing MattersÔÇŐÔÇöÔÇŐSaginaw Valley State University</a> <br><a href="">5 Reasons Why Writing in Business is Important in Generating Better Business┬áResults</a></p> <p>And also I want to talk about Documentation in my next article. So see you there. Have a good day.┬áÔťő</p> <img src=";referrerSource=full_rss&amp;postId=e786fd6016ae" width="1" height="1" alt="">
Environment Setup on Windows/Mac for IT People
<figure><img alt="" src="*gUdmLNqjnxCyxq8i.jpg"></figure><p>In this article, I will share the common environment setup with you. You can be a frontend developer, a backend developer, QA engineer, or a product manager. I will share the common requirements for any IT person. We will go forward step by step. LetÔÇÖs say you get a new computer from your company. And you need to make your computer ready. Then follow the following steps and install the programs. Also, I will add a signature to show you which program I installed and I am┬áusing.</p> <h4>1. <a href="">(MAC) homebrew (Package Manager)</a>┬á­čÉ×</h4> <ul><li>Open its website and follow the instructions and install it in the correct┬áway.</li></ul> <p><a href="">Homebrew</a></p> <ul><li>(<strong>Optional</strong>) You can install some packages like the one below. Even if you are a UX/UI designer you may also need to use git at some point. So you should decide on┬áit.</li></ul> <pre>brew install tree ­čÉ× (It allows you to view all files in a tree view)<br>brew install node ­čÉ×<br>brew install git ­čÉ×<br>brew install graphql-playground<br>brew install ruby<br>brew install python<br>brew install kotlin<br>brew install postgresql<br>brew tap heroku/brew &amp;&amp; brew install heroku</pre> <h4>1.1. GIT</h4> <p>After you install git like above with brew. You should set your defaultBranch, name, and email┬ábelow.</p> <pre>git config --global init.defaultBranch main<br>git config --global "Mucahid Yazar"<br>git config --global <a href=""></a></pre> <p>And generate an ssh key and add it to your GitHub account by using the instructions on Github documentation.</p> <p><a href=""></a></p> <h4>2. (MAC/Windows) Browser Installation, Settings, and Extension</h4> <ul> <li>Everyone needs to use a browser even if it is a very old computer. So choose yours and use it. I prefer you to use Brave or Chrome.<br>- Brave, ­čÉ×<br>- Google Chrome, ­čÉ×<br>- Firefox, <br>- Opera, <br>- Tor┬áBrowser</li> <li>Add a home button to your browser and open the most opened website by you.┬á­čÉ×</li> <li>And set your browser to open ÔÇťLatest closed websitesÔÇŁ after you open your browser again.┬á­čÉ×</li> <li>Log in to your Google Account and sync your browser with your browser.┬á­čÉ×</li> <li>Some of the extensions. that I am using.<br>- Adguard ­čÉ× / Adblock, <br>- Apollo Client Developer Tools,<br>- JSON Viewer, ­čÉ×<br>- Momentum, <br>- React Developer Tools, ­čÉ×<br>- Redux DevTools, ­čÉ×<br>- Wappalyzer, ­čÉ×<br>-, ­čÉ×<br>- Colorzilla, ­čÉ×<br>- Whatfont, <br>- Testing Playground, ­čÉ×<br>- Vue Devtools, <br>- Lighthouse, ­čÉ×<br>- Grammarly, ­čÉ×<br>- Remembery ­čÉ×</li> </ul> <h4>3. (MAC/Windows) <a href="">Crone</a> (Calendar App)┬á­čÉ×</h4> <p><a href="">Cron | Early access</a></p> <ul><li>This is the coolest calendar app that I have seen so far. Even you can install it on your windows computer. I think you need to give it a try.┬á:)</li></ul> <h4>4. (MAC/Windows) <a href="">Slack</a> (Communication App)┬á­čÉ×</h4> <p><a href="">Slack is your digital HQ</a></p> <ul><li>Install Slack to communicate with your┬áteam.</li></ul> <h4>5. (MAC/Windows) Terminal</h4> <h4> <a href="">5.1. Warp</a>┬á­čÉ×</h4> <p><a href="">Warp: The terminal for the 21st century</a></p> <ul><li>I am using warp for a few months and it is really awesome in one word. It has a beautiful UI and it is easy to use. If you wonÔÇÖt use warp you will use iTerm. But that way, you should install some more extensions to improve your terminal experience.</li></ul> <h4>5.2. iTerm2</h4> <p><a href="">iTerm2 - macOS Terminal Replacement</a></p> <ul><li>Or as I said above you can install┬áiTerm2.</li></ul> <h4>5.2.1. Terminal Helper Tools (Optional)</h4> <p>If you will use iTerm instead of Wrap, you can/should one of these extensions.</p> <h4></h4> <p><a href="">Fig</a></p> <h4> oh-my-zsh</h4> <p><a href=""></a></p> <p>- zsh-autosuggestions<br>- zsh-syntax-highlighting</p> <h4>6. (MAC/Windows) Music┬áApp</h4> <ul><li>Some alternatives<br>- Spotify ­čÉ×<br>- Youtube Music<br>- Apple┬áMusic</li></ul> <p><a href="">Listening is everything</a></p> <h4>7. (MAC/Windows) Notion┬á­čÉ×</h4> <p><a href="">Notion - One workspace. Every team.</a></p> <ul><li>This is the best note app I have ever seen today. You can create everything with Notion. Even a website.┬á:)</li></ul> <h4>8. (MAC/Windows) Design (UI/UX)┬áApp</h4> <p><a href="">Figma: the collaborative interface design tool.</a></p> <ul><li>There are some alternatives. But I think Figma is going to moon for a couple of years. So my favorite one is that. And I will put some of the alternatives.<br>- Figma ­čÉ×<br>- Sketch (Just for MAC)<br>- Adobe XD<br>- Zeplin<br>- Photoshop</li></ul> <h4>9. (MAC/Windows) 2FA (UI/UX)┬áApp</h4> <p><a href="">Authy | Two-factor Authentication (2FA) App &amp; Guides</a></p> <ul><li>Most applications force us to set up a 2FA process to provide our safety. So we should use a 2fa application. You should install this 2FA application on one more device for me. The most popular one is Authy. But I will also put some of them below.<br>- Authy ­čÉ×<br>- Google Authenticator</li></ul> <h4>10. (MAC/Windows) File Management App</h4> <p>There are a few alternatives. But it depends on your case. If you have a Macbook you should use iCloud. I would not you to use the other ones. But if you use Windows or Linux you can choose one of the other┬áones.</p> <ul> <li>iCloud ­čÉ×</li> <li>Google Drive</li> <li>One Drive</li> </ul> <h4>11. (MAC/Windows) Developer Apps</h4> <p>- Docker ­čÉ×<br>- Postman ­čÉ×<br>- MongoDB Compass ­čÉ×<br>- Visual Studio Code ­čÉ×<br>- Android Studio ­čÉ×<br>- (MAC) Xcode┬á­čÉ×</p> <h4> <strong>12. (MAC/Windows) MongoDB Community &amp; MongoDB Compass (Optional) </strong>­čÉ×</h4> <p>1. Follow these instructions</p> <pre><a href=""></a></pre> <p>2. Download and install MongoDB Compass <a href=""></a></p> <p>Use the command brew list to see all installed packages</p> <h4>13. (MAC/Windows) VSCode &amp; Settings┬á­čÉ×</h4> <p>I am currently using <a href="">SynthWave </a>ÔÇÖ84 as a theme of┬áVSCode.</p> <h4>13.1. Typeface</h4> <p><strong>Code Editor Font</strong>: <em>Dank Mono </em>­čÉ×<br><strong>Terminal Font</strong>: <em>FuraMono Nerd Font┬á</em>­čÉ×</p> <ul> <li><a href="">JetBrains Mono: A free and open source typeface for developers</a></li> <li><a href="">MonoLisa</a></li> <li><a href="">Dank Mono: The coding typeface for aesthetes</a></li> <li><a href="">GitHub - tonsky/FiraCode: Free monospaced font with programming ligatures</a></li> </ul> <h4>13.2. Visual Studio Code┬á­čÉ×</h4> <p>If you install VSCode the first time, make a clean installation with my following instructions. Then install ÔÇťSettings SyncÔÇŁ and save your settings to the Cloud. In this way, you would get and keep a backup save on the cloud and when you install VSCode again you will get all of your settings, and shortcuts with just one┬áclick.</p> <pre># The shortcuts of Settings Sync<br># Upload<br>SHIFT + OPTION + U<br># Download<br>SHIFT + OPTION + D</pre> <h4>13.2.1. Extensions (Optionals) ­čÉ×</h4> <p>You should install the packages that you┬áneed.</p> <pre>code --install-extension auto-close-tag</pre> <pre>code --install-extension auto-rename-tag</pre> <pre>code --install-extension beautify</pre> <pre>code --install-extension better-comments</pre> <pre>code --install-extension code-settings-sync</pre> <pre>code --install-extension color-highlight</pre> <pre>code --install-extension copilot</pre> <pre>code --install-extension cypress-snippets</pre> <pre>code --install-extension dotenv</pre> <pre>code --install-extension es7-react-js-snippets</pre> <pre>code --install-extension fig</pre> <pre>code --install-extension gitlens</pre> <pre>code --install-extension glance</pre> <pre>code --install-extension grammarly</pre> <pre>code --install-extension html-snippets</pre> <pre>code --install-extension JavaScriptSnippets</pre> <pre>code --install-extension jest-snippets</pre> <pre>code --install-extension jestRunIt</pre> <pre>code --install-extension jquerysnippets</pre> <pre>code --install-extension LiveServer</pre> <pre>code --install-extension markdown-all-in-one</pre> <pre>code --install-extension markdown-preview-enhanced</pre> <pre>code --install-extension material-icon-theme</pre> <pre>code --install-extension mdx</pre> <pre>code --install-extension moonlight</pre> <pre>code --install-extension night-owl</pre> <pre>code --install-extension path-intellisense</pre> <pre>code --install-extension polacode</pre> <pre>code --install-extension prettier-vscode</pre> <pre>code --install-extension prisma</pre> <pre>code --install-extension quicktype</pre> <pre>code --install-extension quokka-vscode</pre> <pre>code --install-extension react-native-react-redux</pre> <pre>code --install-extension remote-containers</pre> <pre>code --install-extension remote-wsl</pre> <pre>code --install-extension solidity</pre> <pre>code --install-extension spellright</pre> <pre>code --install-extension sqlite-viewer</pre> <pre>code --install-extension styled-components-snippets</pre> <pre>code --install-extension swift</pre> <pre>code --install-extension synthwave-vscode</pre> <pre>code --install-extension vscode-commitizen</pre> <pre>code --install-extension vscode-docker</pre> <pre>code --install-extension vscode-eslint</pre> <pre>code --install-extension vscode-github-actions</pre> <pre>code --install-extension vscode-graphql</pre> <pre>code --install-extension vscode-html-css</pre> <pre>code --install-extension vscode-import-cost</pre> <pre>code --install-extension vscode-jest</pre> <pre>code --install-extension vscode-kubernetes-tools</pre> <pre>code --install-extension vscode-react-native</pre> <pre>code --install-extension vscode-sqlite</pre> <pre>code --install-extension vscode-styled-components</pre> <pre>code --install-extension vscode-tailwindcss</pre> <pre>code --install-extension vscode-todo-highlight</pre> <pre>code --install-extension vscode-typescript-next</pre> <pre>code --install-extension vscode-versionlens</pre> <pre>code --install-extension vscode-yaml</pre> <pre>code --install-extension vscodeintellicode</pre> <h4>14. (MAC/Windows) NPM Packages Globally (Optional)</h4> <pre>npm i -g yarn ­čÉ×<br>npm i -g babel-cli<br>npm i -g eslint<br>npm i -g expo-cli<br>npm i -g firebase-tools<br>npm i -g gatsby-cli<br>npm i -g jest<br>npm i -g lighthouse<br>npm i -g netlify-cli<br>npm i -g newman<br>npm i -g node-sass<br>npm i -g parcel-bundler<br>npm i -g pm2<br>npm i -g prettier<br>npm i -g serve<br>npm i -g spaceship-prompt<br>npm i -g surge<br>npm i -g typescript<br>npm i -g update<br>npm i -g vercel</pre> <p>Use the command npm list -g --depth 0 to see all installed packages</p> <h4>15. (MAC/Windows) PIP Packages (Optional)</h4> <p>Use the command pip or pip3 to install depending on your┬ásystem.</p> <pre>pip3 install astroid<br>pip3 install autopep8<br>pip3 install certifi<br>pip3 install chardet2<br>pip3 install click<br>pip3 install Flask<br>pip3 install Flask-Cors<br>pip3 install harperdb<br>pip3 install idna<br>pip3 install isort<br>pip3 install itsdangerous<br>pip3 install Jinja<br>pip3 install lazy-object-proxy<br>pip3 install MarkupSafe<br>pip3 install mccabe<br>pip3 install psycopg2<br>pip3 install psycopg2-binary<br>pip3 install pycodestyle<br>pip3 install pylint<br>pip3 install python-dotenv<br>pip3 install requests<br>pip3 install setuptools<br>pip3 install six<br>pip3 install toml<br>pip3 install urllib3<br>pip3 install Werkzeug<br>pip3 install wrapt</pre> <p>Use the command pip3 list or pip list to see all installed packages</p> <h4>16. (MAC) Emojis┬á­čÉ×</h4> <p><a href="">Rocket - the best emoji app for Mac</a></p> <p>And also if you are using a MAC, I absolutely prefer you to look at my Macbook hint article. I am crazy sure you will find some useful things for yourself.</p> <p><a href="">27 Macbook Tips &amp; Tricks in 2022</a></p> <p>See you at the next one.┬á­čĹő</p> <img src=";referrerSource=full_rss&amp;postId=355d075fe20a" width="1" height="1" alt="">
The story of NULL
<p>undefined, JavaScriptde kesin yoklu─ču s├Âyleyen bir primitive valuedir. undefined, 1998 de <a href="">JavaScript 1.3</a> e kadar direct olarak eri┼čilebilir de─čildi. Buda bize nullÔÇÖun o zaman, bir de─čerin olmad─▒─č─▒n─▒ a├ž─▒k├ža s├Âyleyen bir de─čer olarak kullan─▒ld─▒─č─▒ i├žin tasarland─▒─č─▒n─▒ s├Âyler. Initialize olmam─▒┼č de─čerler otomatik olarak undefined de─čerini al─▒rlar. undefined ise ECMAScript spesificationslar─▒nda <a href="">t├╝r tiplerinden birisidir</a>.</p> <p>null objectlerde kas─▒tl─▒ istenilen, b─▒rak─▒lan yoklu─ču ifade eden primitive valuedir. null da ECMAScript spesificationslar─▒nda <a href="">t├╝r tiplerinden birisidir</a>.</p> <p>JavascriptÔÇÖte null Java ile birlikte ├žal─▒┼čabilirli─či sa─članmak amac─▒yla tasarland─▒. <a href="">Hem g├Âr├╝n├╝m perspektifinden, hemde programlama perspektifinden ├Ât├╝r├╝</a>. Hem Brendan Eich hemde di─čer geli┼čtiriciler, 2 absence yani yokluk valuesinin olmas─▒ndan ho┼čnut olmad─▒klar─▒n─▒ ifade ettiler fakat 1995 de yinede EichÔÇÖe Javascripti Javaya benzetme emri verdiler.</p> <blockquote>E─čer y├Ânetimden ÔÇťJava gibi yapÔÇŁ emrini almasayd─▒m ve daha fazla zaman─▒m olsayd─▒ (Bu iki sebebi ├ž├Âzmek zordu), ÔÇťHer┼čey bir objectÔÇŁ mant─▒─č─▒na benze bir approach tercih ederdim. Yani Boolean, Number, String sarmalay─▒c─▒lar─▒ yok, undefined null yok gibi. Ahh.<br><a href="">Brendan┬áEich</a>:</blockquote> <p>Javan─▒n strongly-typed yap─▒s─▒ndan ├Ât├╝r├╝ null sadece typed variableslara yani typeÔÇÖ─▒ belirli variablelara assign edilebiliyordu. Ve Eich, javadaki null konseptine uyum sa─člamas─▒ amac─▒yla null i├žin object prototype chaninin en ├╝st├╝nde ├Âzel bir konum se├žti. (i.e.(yani) the top of the reference types). Ve null type ─▒n─▒, ÔÇťobject-type primitivesÔÇŁ ─▒n bir par├žas─▒ oalrak dahil etti. Bu y├╝zden typeof null, ÔÇśnullÔÇÖ de─čil ÔÇśobjectÔÇÖ┬ád├Âner.</p> <p>Typeof operat├Âr├╝, 19 Agustos 1996ÔÇÖda <a href="">JavaScript 1.1</a> releases─▒nden k─▒sa bir s├╝re sonra┬áeklendi.</p> <h4>typeof null ===┬áÔÇśobjectÔÇÖ</h4> <p>From <a href="">the V8┬áblog</a>:</p> <p>typeof null, null un kendisinin bir type olmas─▒na ra─čmen null de─čil object return eder. Nedenini anlamak i├žin Javascriptteki typeslar─▒n 2 gruba ayr─▒ld─▒─č─▒n─▒ d├╝┼č├╝n├╝n.</p> <p>1. objects (i.e. the Object┬átype)</p> <p>2. primitives (i.e. any non-object value)</p> <p>Bu y├╝zden null ÔÇťno object valueÔÇŁ anlam─▒ndayken, undefined ÔÇťno valueÔÇŁ anlam─▒ndad─▒r. Daha iyi anlamak i├žin a┼ča─č─▒da ki grafi─če┬ábakal─▒m.</p> <figure><img alt="" src="*tR64wIvXmjlCY9FhA9LKHg.png"></figure><p>Bu d├╝┼č├╝nce ├žizgisini takip ederek, Brendan Eich JavaScriptÔÇÖi, Java ruhu i├žinde, sa─č taraftaki t├╝m de─čerler, yani t├╝m objectler ve null de─čerler i├žin typeof return ÔÇśobjectÔÇÖ yapmak ├╝zere tasarlad─▒. ─░┼čte bu niye typeof null === ÔÇśobjectÔÇÖ niye null de─čilin sebebidir.</p> <figure><img alt="" src="*4pjQl94-HXmBNnusTTAf6Q.png"></figure><p>Bu y├╝zden Eich, primitive typeslar─▒n hiyera┼čisini Java ile uyumluluk sa─člayabilmesi i├žin tasarlad─▒. Buda onu null i├žin ÔÇťobject-type primitivesÔÇŁ larda pozisyonlamas─▒na ├Ânc├╝l├╝k etti. Bunu yans─▒tmak i├žinde, nulldan sonra Javascripte typeof eklendi─činde, typeof null un ÔÇťobjectÔÇŁ d├Ânmesini se├žti.</p> <p>Javascript geli┼čtiricileri aras─▒nda typeof null === ÔÇťobjectÔÇŁ s├╝prizi, hem null hemde undefined a sahip weakly-typed language (JavaScript) ile sadece null a sahip bir ba┼čka strongly-typed language (Java) aras─▒nda bir impedance mismatch (or abstraction leak) olarak ifade edildi. Ki Javada null, bir primitive type a de─čil, kesinlikle bir reference type ─▒na at─▒fta bulunmak i├žin tasarlanm─▒┼čt─▒r.</p> <p><strong>Bunlar─▒n hepsi mant─▒kl─▒, a├ž─▒klanabilir ve savunulabilir. </strong><strong>typeof null === "object" bir bug de─čil fakat Java ile birlikte ├žal─▒┼čabilir olmas─▒n─▒n ikinci dereceden bir┬áetkisi.</strong></p> <p>undefined─▒n bir valuenin yokluk durumunu g├Âstermesi ve null─▒n ├Âzellikle bir objectin yokluk durumunu g├Âstermesi dahil bir dizi geriye d├Ân├╝k akla yatk─▒n hale getirme conventions─▒ ortaya┬á├ž─▒kt─▒.</p> <p>Brendan Eich in bu konuyla alakal─▒ ilgili konu┼čmas─▒n─▒ g├Ârsel olarak a┼ča─č─▒ya b─▒rak─▒yorum.</p> <h3>BrendanEich on Twitter: "JS was supposed to interconnect with Java, including object refs that could be null. Blame Java, yet again. / Twitter"</h3> <p>JS was supposed to interconnect with Java, including object refs that could be null. Blame Java, yet again.</p> <figure><img alt="" src="*k5-rfBrK3IUQWNkFmolJ1w.png"></figure><img src=";referrerSource=full_rss&amp;postId=a0bcdde250c6" width="1" height="1" alt="">
27 Macbook Tips &amp; Tricks in 2022
<p>This week I bought a Macbook Pro 16". So I just wanted to set and use my Macbook more efficiently. Before the Macbook I was using Windows for 15 years. Of course, It is not my first time with Macbook. I am also using Macbook for more than 3 years in my professional career. But I wasnÔÇÖt thinking to go forward by Mac this much. I never thought I will use Mac rest of my life since Apple released the last Macbook in 2021. Who knows I can buy another Windows computer but I am sure I will not use Windows for programming again. I can tell you why this another article. In a nutshell, I do want to integrate myself fully into Mac. So I searched and watched lots of videos and want to share them with you in this article. Have a good┬áread.</p> <figure><img alt="" src="*AJGezJPpIWhmCdeD.jpg"></figure><h4>1. Custom Screen Lock┬áMessage</h4> <p>You can set a custom message for your screen lock. In this way, if you lost your mac somewhere then someone who found and open your mac can see your message and contact you. My screen lock message is My Name: ÔÇťMy Number; My BrotherÔÇÖs Name: His┬áPhone;ÔÇŁ</p> <figure><img alt="" src="*PkYBAQmjwits5O_EkS7Jbw.png"></figure><h4>2. Emojis</h4> <p>control + command + space Ôçĺ This is the shortcut to how you can see the panel┬ábelow.</p> <figure><img alt="" src="*FuguMLUY_A6vn4OJLO3MOw.png"></figure><h4>3. All Open┬áPages</h4> <p>You can touch by your three-finger and swipe them up on the touch bar. You will see all windows┬ábelow</p> <figure><img alt="" src="*7EJ3GiU9Kj0hS_yZVwKQ0Q.png"></figure><h4>4. Hot┬áCorners</h4> <p>I think no one does not wants to minimize all screens to see the desktop. There is a way. And it is hot corners. You can create another trick by hot corners. Open Spotlight search and search for Mission Control and open it. And set the right corner as Desktop. After that, you will see the window when you take your mouse right below corner. And do that again you will return┬áback.</p> <figure><img alt="" src="*eiw4WFzrGfi9A16H6VMUcA.png"></figure><h4>5. Privacy</h4> <p>You can add the files which you do not want to show in search┬áresults.</p> <figure><img alt="" src="*uYjxImmrUR4Nmh6hPuWhew.png"></figure><h4>6. SidebarÔÇŐÔÇöÔÇŐFinder Preferences</h4> <p>You can add some items to show on your┬ásidebar.</p> <figure><img alt="" src="*OEBRo1sDRJRY9YtF0E-WeQ.png"></figure><p>And you will see the side bar like┬ábelow.</p> <figure><img alt="" src="*y0H2n4L7i1X6m9qxgI5hVw.png"></figure><h4>7. New Finder WindowÔÇŐÔÇöÔÇŐFinder Preferences</h4> <p>When you open your finder you will see the recent page that you open. Instead of this, you can set another path as a default┬áwindow.</p> <figure><img alt="" src="*0FABqQw6MjVxObjX_oBBgA.png"></figure><h4>8. Three Finger┬áDrag</h4> <p>As default, you should click the head of the window to drag and drop a window. But that is not easy if you are using the touchpad of a mac. There is an easy way to do that. That is this. Do that and enjoy with your touchpad. ­čśŐ</p> <figure><img alt="" src="*t5eIdHsnUwAzeHlQtePp4A.png"></figure><h4>9. Tap to┬áClick</h4> <p>As you know clicking is also not easy by the touchpad. Instead of using press the touchpad let's set it as┬átouch.</p> <figure><img alt="" src="*oofGVWw2OnrVGokUx2iDPA.png"></figure><h4>10. Desktop┬áItems</h4> <p>I like to see some of the shortcuts on destop. like Macintosh HD. You can also do that like┬áme.</p> <figure><img alt="" src="*ovxCaO97zNhbyeF_l7Qxgw.png"></figure><h4>11. Dark┬áMode</h4> <figure><img alt="" src="*UANOfcwoD7UVjm0s3kBoEA.png"></figure><h4>12. Multi-Touch ID</h4> <p>I think second or multi-touch id is one of the most important things in MAC. You can add your other finger or you can add your relative's finger.</p> <figure><img alt="" src="*gyl6di8VWm18QlLfuzF9uQ.png"></figure><h4>13. Turn off the Notifications of the Unnecessary Apps</h4> <figure><img alt="" src="*z3g5hfmYg-4g3FVvbi7Vkg.png"></figure><h4>14. Connect for┬áSharing</h4> <p>If you use Iphone like me, you do want to share some files between your mac and phone. This is a good way for┬áit.</p> <ul> <li>open ÔÇťFilesÔÇŁ in your┬áphone</li> <li>Click the ÔÇťÔÇŽÔÇŁ which is top right┬ácorner</li> <li>Then ÔÇťConnect to ServerÔÇŁ and write your computer name with┬áÔÇť.localÔÇŁ</li> </ul> <p>And you are connected.</p> <figure><img alt="" src="*GDFviuaIU8m1SJkjZ7hwlg.png"></figure><h4>15. Picture in┬áPicture</h4> <figure><img alt="" src="*MRDeN54YiyWBT8QxxoFdsQ.png"></figure><figure><img alt="" src="*Hvg1KBVz_AFpLvUPuYnCxA.png"></figure><h4>16. Automatically Hide and Show the┬áDock</h4> <figure><img alt="" src="*s2zJLtXDVSjfNkGGINFvEw.png"></figure><h4>17. Hide Recent Applications</h4> <p>I donÔÇÖt like to see recent applications in dock so I am hiding them. Because the dock bar has a limited┬áarea.</p> <figure><img alt="" src="*_EMOh3xhp2sNjNk4MGBFFg.png"></figure><h4>18. Use┬áStacks</h4> <p>This shows the same files as just a card. Just try it and discover it by yourself.</p> <figure><img alt="" src="*x9xV-0Xvgo5H7-TCVQGt1w.png"></figure><h4>19. Show Status┬áBar</h4> <p>I like to see Status Bar. If you are a person like me then click the View and Show the Status Bar like┬áme.</p> <figure><img alt="" src="*qDDKZuu_36_qHNG2PcFAJg.png"></figure><h4>20. Increase Your Track┬áSpeed</h4> <figure><img alt="" src="*fIptskvDxvHeE5yoqrZUPA.png"></figure><h4>21. Move Sound Icon to the┬áBar</h4> <p>Click the Toggles Icon which is on the left of the Siri, then press the volume for a few seconds then drag it to the┬ábar.</p> <figure><img alt="" src="*ecYphCcSLk8B__B0e5-k3Q.png"></figure><h4>22. Change the Screenshot Directory</h4> <p>By default the screenshots will save to your desktop when you took one. It makes like a trash box our destop. (At least I feel like that) So let create a folder which name is screenshots and set it as the screenshot location.</p> <ul> <li>Command + Shift +┬á5</li> <li>Options &gt; Other Locations</li> </ul> <p>and chose the folder which you┬ácreate.</p> <h4>23. Macbook┬áName</h4> <p>If you want to change your Macbook name, you can search Sharing Preferences on Spotlight Search and use this┬ápage.</p> <figure><img alt="" src="*GDFviuaIU8m1SJkjZ7hwlg.png"></figure><h4>24. Multi-Language for┬áKeyboard</h4> <p>I am a Turkish guy and I have a Turkish keyboard layout on my MAC. But I also have an external English layout keyboard which is Keychron K2. And I am using the English language when I am coding something. If you are a guy like me you can add the English Language to your system. Open the Keyboard your System Preferences and add it like┬ábelow.</p> <figure><img alt="" src="*0mP_Cusw3Vol-CJMlfqvuA.png"></figure><h4>25. Disable Unnecessary Spotlight Options</h4> <p>I just use ÔÇťApplicationsÔÇŁ, ÔÇťFoldersÔÇŁ, ÔÇťPDF DocumentsÔÇŁ and ÔÇťSystem PreferencesÔÇŁ.</p> <figure><img alt="" src="*G7Qz500FoNEMSdN40pW29g.png"></figure><h4>26. Uncheck Scroll direction: Natural</h4> <p>In this way, you can use scrolling in a familiar┬áway.</p> <figure><img alt="" src="*TvgZKRQJEecC3egDFda4sQ.png"></figure><h4>27. Show Tab/Path/Status Bar</h4> <figure><img alt="" src="*oOd_oIWKv1noeZhbE7mePA.png"></figure><img src=";referrerSource=full_rss&amp;postId=98072c53366a" width="1" height="1" alt="">
<p>Uzun bir aradan sonra tekrardan herkese esenlikler. Hepinize g├╝zel, verimli bir 2022 y─▒l─▒ diliyorum. Bug├╝n URL API ─▒n─▒ inceleyece─čiz. Keyifli okumalar diyerek sizleri direkt konuya b─▒rak─▒yorum.</p> <p><strong>URL</strong> API aray├╝z├╝, urllerimizi parse, construct, normalize, and encode <a href="">e</a>tmek i├žin kullan─▒l─▒r. URL komponentini bu ┼čekilde kolayl─▒kla okuyabilir ve d├╝zenleyebiliriz. A┼ča─č─▒daki step by step ├Ârnekle bunu ├žok daha iyi anlayaca─č─▒z. E─čer URL aray├╝z├╝n├╝ browser─▒n─▒z desteklemiyorsa window aray├╝z├╝n├╝n URL propertysi ilede bunu yapabilirsiniz.</p> <h3>Get Started</h3> <p>Baslarken ilk olarak bir URL in yap─▒s─▒ nas─▒l, gelin onu ├Â─črenelim. A┼ča─č─▒daki resim bunu bize gayet a├ž─▒k bir ┼čekilde anlat─▒yor ve g├Âsteriyor.</p> <figure><img alt="" src="*NPkuyZEpAfabhBpm.png"></figure><h4>new URL(ÔÇśurlLinkÔÇÖ)</h4> <pre>new URL(ÔÇś<a href=""></a>ÔÇÖ)</pre> <p>Buradaki gibi URL tan─▒m─▒ yapabilir ve bunu a┼ča─č─▒daki gibi bir de─či┼čkene atayabiliriz.</p> <pre>let x = new URL(ÔÇś<a href=""></a>ÔÇÖ)</pre> <p>Ve istersek bu de─či┼čkenden a┼ča─č─▒daki gibi URL imizi ├žekip ├ž─▒kartabiliriz.</p> <pre>x.toString() // <a href=""></a></pre> <h4>.searchParams.append(ÔÇśkeyÔÇÖ, ÔÇśvalueÔÇÖ)</h4> <p>Veya param ve queryler ekleyebiliriz.</p> <pre>x.searchParams.append(ÔÇścategoryÔÇÖ, ÔÇśelectronicÔÇÖ)<br>x.toString() // <a href=""></a>/?category=electronic<br>x.searchPArams.append(ÔÇśsortÔÇÖ, ÔÇśtopÔÇÖ)<br>x.toString() // <a href=""></a>/?category=electronic&amp;sort=top</pre> <h4>.href</h4> <p>Veya bunu┬á.href ile de yapabiliriz a┼ča─č─▒daki gibi</p> <pre>x.href // <a href=""></a>/?category=electronic&amp;sort=top</pre> <h4>.host</h4> <p>Veya istersek a┼ča─č─▒daki gibi host yani as─▒l domain ad─▒n─▒ direkt alabiliriz.</p> <pre> //</pre> <h4>.origin</h4> <p>Veya urlÔÇÖin scheme, domain ve portunu sadece istiyorsak origin ile bunu a┼ča─č─▒daki gibi basit├že halledebiliriz. Biz ilk tan─▒mlarken bir port vermedi─čimiz i├žin URL imize bizde port g├Âz├╝kmeyecektir tabi┬áki.</p> <pre>x.origin // <a href=""></a></pre> <h4>.username &amp;┬á.password</h4> <p>URL imize a┼ča─č─▒daki gibi <strong>username password </strong>bilgileri ayarlayabiliriz, atayabiliriz.</p> <pre>x.username = ÔÇśtestÔÇÖ<br>x.username // test<br>x.href // <a href=""></a>/?category=electronic&amp;sort=top<br>x.password = ÔÇś12345ÔÇÖ<br>x.password // 12345<br>x.href // <a href=""></a>/?category=electronic&amp;sort=top</pre> <p>Veya a┼ča─č─▒daki gibi direkt tan─▒mlayarakda URL imizi olu┼čturabiliriz.</p> <pre>const url = new URL('');<br>console.log(url.password) // Logs "flabada"</pre> <h4>.pathname</h4> <p><strong>pathname </strong>lerimizide direkt ayarlayabilir, atayabiliriz a┼ča─č─▒daki gibi.</p> <pre>x.pathname = ÔÇśankaraÔÇÖ<br>x.pathname // ankara<br>x.href // <a href=""></a>/ankara?category=electronic&amp;sort=top</pre> <h4><strong>.port</strong></h4> <p>Port lar─▒m─▒zda ayn─▒ pathnamelerimiz gibi ayarlanabilir ve atanabilir.</p> <pre>x.port= ÔÇś3000ÔÇÖ<br>x.port // 3000<br>x.href // <a href=""></a>:3000/ankara?category=electronic&amp;sort=top</pre> <h4>.protocol</h4> <p>URL imizin protocolunun ne oldu─čunuda┬á.<strong>protocol </strong>property si ile ├Â─črenebiliriz.┬á<strong>:</strong> i┼čareti de dahil a┼ča─č─▒daki gibi.</p> <pre>x.protocol= ÔÇśhttps:ÔÇÖ</pre> <p>Ve bunu da asl─▒nda manipule edebilir ve de─či┼čtirebiliriz, di─čer properties lerde oldu─ču┬ágibi.</p> <pre>x.protocol= ÔÇśhttp:ÔÇÖ<br>x.protocol // 'http:'<br>x.href // <a href=""></a>:3000/ankara?category=electronic&amp;sort=top</pre> <h4>.search</h4> <p>URL imizdeki┬á? ile ba┼člayarak b├╝t├╝n parametrelerin stringini d├Âner bize. Di─čer property ler gibi buda de─či┼čtirilebilir.</p> <pre> = ÔÇś?category=electronic&amp;sort=topÔÇÖ<br> '?category=electronic&amp;sort=popular'<br>x.href // <a href=""></a>:3000/ankara?category=electronic&amp;sort=popular</pre> <h3>METHODS</h3> <h4>.toString() &amp;┬á.toJSON()</h4> <p>.href property si gibi b├╝t├╝n URL i verir bize bu ikisi. Fakat ikisi de yeniden assign edilemez, yeniden value atanamaz diyebiliriz fark┬áolarak.</p> <pre>x.toString() = <a href=""></a>:3000/ankara?category=electronic&amp;sort=popular<br>x.toJSON() = <a href=""></a>:3000/ankara?category=electronic&amp;sort=popular</pre> <h3>STATIC METHODS</h3> <h4>URL.createObjectURL(object, options)</h4> <p>Belirli bir object i├žin URL olu┼čturur.</p> <p><strong>object </strong>URL ihtiyac─▒ olan bir de─čerdir. Genellikle bir input diyebiliriz.</p> <pre><strong>var url = URL.createObjectURL(inputElement.files[0]);<br>imgElement.src = url;</strong></pre> <pre><strong>URL.createObjectURL(object, options);</strong></pre> <p><strong>options </strong>ise bu olu┼čturdu─čumuz URL objecti i├žin bir ayarlar k─▒sm─▒dir. Mesela a┼ča─č─▒da <strong>oneTimeOnly </strong>optionsunu vererek bu URL de─či┼čkeninin asl─▒nda <a href=""><strong>revokeObjectURL</strong></a><strong> </strong>e ihtiyac─▒ olmad─▒─č─▒n─▒ ├ž├╝nk├╝ sadece 1 defa kullan─▒laca─č─▒n─▒ s├Âyleriz.</p> <pre><strong>oURL = URL.createObjectURL(file, {oneTimeOnly: true});</strong></pre> <h4>URL.revokeObjectURL(Object)</h4> <p>URL.createObjectURL ile olu┼čturulmu┼č URL leri revoke etme i┼člemini bu static method ile┬áyapar─▒z.</p> <h3>KAYNAKLAR</h3> <p><a href=""></a></p> <img src=";referrerSource=full_rss&amp;postId=e2d129b93d4c" width="1" height="1" alt="">
Creating a UI Library &amp; Github Actions &amp; Rules, Tests and Version Management
<p>Son 1 ayd─▒r npm paketleri ve buradaki y├Ânetim ve best practiselerle alakal─▒ okumalar ve denemeler yap─▒yordum. Hatta bunlar─▒ yaparken bir tanede kendime ait icomoon-generator ad─▒nda bir libraryde geli┼čtirdim. Bu librarynin ne i┼č yapt─▒─č─▒na niye olu┼čturdu─čuma daha sonra de─činece─čim. Fakat ┼čimdi g├Ârd├╝─č├╝m, ├Â─črendi─čim ve ├žal─▒┼čt─▒─č─▒m bu ┼čeyleri uygulanan best practiselerle birlikte burada size anlatmaya ├žal─▒┼čaca─č─▒m.</p> <figure><img alt="" src="*9tZJmq1VYTIdble0ZgeZRQ.png"></figure><h3><strong>What will we┬ásee?</strong></h3> <p><strong>1. Create a Github Repo<br>2. Creating the Project<br>3. Storybook<br>4. Prettier<br>5. Eslint<br>6. Button Components with Typescript<br>7. styled-components<br>8. prop-types<br>9. API Design<br>10. Composition API<br>11. Tests (jest Settings)<br>12. Tests (@testing-library/react Settings)<br>13. Tests<br>14. Module Formats<br>15. Typescript Declarations<br>16. husky<br>17. semantic-release<br>18. Github Environment Variable<br>19. Github┬áActions</strong></p> <h3>Get Started</h3> <h4>Step 1: Create a Github┬áRepo</h4> <p>Github ├╝zerinde ui-library ad─▒nda bir repository olu┼čturdum. Ve olu┼čtururken┬á.gitignore ve dosyalar─▒n─▒da eklemesini istiyorum.</p> <figure><img alt="" src="*pH6H3mVpnymO7zx6ytYtUg.jpeg"></figure><h4>Step 2: Creating the┬áProject</h4> <p>npx create-react-app ui-libraryÔÇŐÔÇöÔÇŐtemplate typescript</p> <p>Yukar─▒da ki kodu ├žal─▒┼čt─▒rarak create-react-app ile typescriptli bir react projesi olu┼čturuyoruz.</p> <p>Sonra olu┼čturdu─čumuz github reposu ile bu olu┼čturdu─čumuz projeyi senkronize ediyoruz. Sonra da a┼ča─č─▒daki gibi package.json dosyam─▒z─▒ kendimize ve olu┼čturdu─čumuz repositorye g├Âre bilgilerini d├╝zenliyoruz.</p> <a href=""></a><p>Daha sonra root dizinimize a┼ča─č─▒da ki ÔÇťtsconfig.jsonÔÇŁ dosyas─▒n─▒ ekliyoruz.</p> <a href=""></a><p>Sonra a┼ča─č─▒da ki gibi file-structure olu┼čturduktan sonra,</p> <figure><img alt="" src="*bnxz4xRvRm2dDbo5omNTjQ.png"></figure><p>ÔÇťButtonÔÇŁ component─▒m─▒ olu┼čturuyorum.</p> <a href=""></a><a href=""></a><a href=""></a><h4>Step 3: Storybook</h4> <p>Ve ┼čimdi de Storybook entegrasyonumuzu yapaca─č─▒z. Bunun i├žni tek yapmam─▒z gereken a┼ča─č─▒da ki kodu ├žal─▒┼čt─▒rarak projemize storybookÔÇÖu entegre┬áetmek.</p> <p>npx sb┬áinit</p> <p>Kurulumla birlikte gelen ÔÇťstoriesÔÇŁ klas├Âr├╝n├╝ proje d─▒┼č─▒ndaki bir dizine ta┼č─▒y─▒n veya silin. Ta┼č─▒rsan─▒z daha sonra bu ├Ârneklere bak─▒p kopyalar ├žekebilirsiniz veya direk silip documentationlarlada ilerleyebilirsiniz.</p> <p>Sonra ÔÇťstoriesÔÇŁ klasor├╝ne gelip ÔÇťintroduction.stories.mdxÔÇŁ ad─▒nda dosya olu┼čturuyoruz ve a┼ča─č─▒dakileri i├žine yap─▒┼čt─▒r─▒yoruz.</p> <p>import { Meta, Description } from ÔÇś@storybook/addon-docs/blocksÔÇÖ;<br>import README from ÔÇś../../README.mdÔÇÖ;<br>&lt;Meta title=ÔÇŁExample/IntroductionÔÇŁ /&gt;<br>&lt;Description&gt;{README}&lt;/Description&gt;</p> <p>Ve daha sonra ÔÇťButton.stories.tsxÔÇŁ story dosyas─▒n─▒ olu┼čturup a┼ča─č─▒da ki kod blogunu ekliyoruz.</p> <a href=""></a><p>Bu y├╝klemelerden sonra hata al─▒rsan─▒z┬á.storybook dosyas─▒ndaki main.js e gelip a┼ča─č─▒da ki typescript blogunu┬áekleyin.</p> <a href=""></a><h4>Step 4:┬áPrettier</h4> <p>─░lk ├Ânce prettieri a┼ča─č─▒daki gibi y├╝kl├╝yoruz.</p> <p>yarn add -D┬áprettier</p> <p>Ve┬á.prettierrc.json ad─▒nda dosya olu┼čturup a┼ča─č─▒daki bir tane ayar─▒ ekliyorum. Siz daha fazla prettier ayar─▒ burada projeniz i├žin ayarlayabilirsiniz tabi ki┬áde.</p> <a href=""></a><p>Ve package.jsona gelip a┼ča─č─▒da ki 2 tane scripti ekliyoruz. Bunlar;</p> <p>- format, prettiere g├Âre dosyalar─▒n formatlanmas─▒n─▒ d├╝zeltilmesini sa─čl─▒yoruz.<br>- lint:format, her┼čeyin bu formatta oldu─čunun teyitini yap─▒yoruz.</p> <a href=""></a><h4>Step 5:┬áEslint</h4> <p>Eslint ilede javascript yaz─▒m kurallar─▒n─▒ set edece─čiz. A┼ča─č─▒daki paketleri ├Âncelikle y├╝kl├╝yoruz.</p> <p>npm installÔÇŐÔÇöÔÇŐsave-dev eslint eslint-config-prettier eslint-plugin-jest eslint-plugin-react eslint-plugin-react-hooks @typescript-eslint/eslint-plugin @typescript-eslint/parser</p> <p>or</p> <p>yarn add -D eslint eslint-config-prettier eslint-plugin-jest eslint-plugin-react eslint-plugin-react-hooks @typescript-eslint/eslint-plugin @typescript-eslint/parser</p> <p>Sonra <strong>ÔÇť.eslintrcÔÇŁ</strong> ad─▒nda bir dosya olu┼čturup i├žine a┼ča─č─▒dakileri yap─▒┼čt─▒r─▒yoruz.</p> <a href=""></a><p>Bu config┬ádosyas─▒;</p> <p>-root, config dosyas─▒n─▒n, root config dosyas─▒ oldu─čunu s├Âyler.<br>-parser, typescriptli eslint rulelar─▒n─▒ parse etmesini s├Âyler.<br>-recommend edilen eslint ayarlar─▒ tan─▒mlan─▒r. <br>-react ve react hookslar─▒n─▒n eslint recommended kurallar─▒ set edilir.<br>-prettier i├žin eslint ayarlar─▒n─▒ set┬áeder.</p> <p>Bu eslint kurallar─▒ typescriptlerle componentlar─▒m─▒z─▒ tan─▒mlamam─▒z─▒ zorunlu tutaca─č─▒ i├žin, Button component─▒m─▒ a┼ča─č─▒da ki gibi d├╝zenliyorum.</p> <a href=""></a><p>A┼ča─č─▒da da <strong>ÔÇťlintÔÇŁ</strong> ad─▒nda yeni bir script tan─▒mlar─▒z. B├Âylece eslint ile ayarlad─▒─č─▒m─▒z ayarlarla yazd─▒─č─▒m─▒z javascript kolar─▒n─▒n kurallara uyup uymad─▒─č─▒n─▒z denetleriz.</p> <a href=""></a><h4>Step 6: Button Components with Typescript</h4> <p>┼×imdi de k├╝t├╝phanemizin ilk ger├žek par├žas─▒ Button component─▒n─▒ ger├žek olarak olu┼čtural─▒m.</p> <p>Button component─▒m─▒z─▒ React.forwardRef ile sar─▒yoruz ve generator olarak HTMLButtonElement veriyoruz ve bu buradaki elementin bir HTMLButtonElementi olaca─č─▒n─▒ s├Âyl├╝yor ve 2. Argument olarak da bu generatore propslarin almas─▒ gereken attribute kurallar─▒ vererek propslar─▒ s─▒n─▒rl─▒yoruz ve onu da React.ComponentsPropsWithoutRef ile &lt;ÔÇÖbuttonÔÇÖ&gt; olmas─▒n─▒ s├Âyl├╝yoruz.</p> <a href=""></a><h4>Step 7: styled-components</h4> <p>Componentlar─▒m─▒z─▒ olu┼čturmak i├žinde styled-components k├╝t├╝phanesinden faydalanaca─č─▒m─▒z i├žin a┼ča─č─▒daki kodla ├Âncelikle y├╝kl├╝yoruz.</p> <p>yarn add -D styled-components @types/styled-components polished<br>or<br>npm install --save-dev styled-components @types/styled-components polished</p> <p>Sonra src alt─▒nda utils ad─▒nda klas├Âr olu┼čturup i├žinde de, colors.ts veya styles.ts ad─▒nda dosyalar─▒m─▒z─▒ olu┼čturup, a┼ča─č─▒da ki de─či┼čkenleri tan─▒ml─▒yoruz.</p> <a href=""></a><p>Daha sonra Button.tsx klas├Âr├╝ne gelip yukar─▒da ki style.ts dosyas─▒n─▒ tan─▒ml─▒yoruz ve bu butonu export ediyoruz ve Button.tsx i├žinde kullan─▒yoruz.</p> <a href=""></a><p>Daha sonra Button.tsx dosyam─▒z da style.ts den gelen styled-component ile olu┼čturdu─čum Button de─či┼čkenini component gibi kullan─▒yorum ve defaultProps tan─▒ml─▒yorum.</p> <a href=""></a><h4>Step 8: prop-types</h4> <p>Prop kontrollerini asl─▒nda typescript ile zaten yap─▒yoruz ama birde ekstra bir k├╝t├╝phane ile de yapabiliyoruz. Biz bunu da ekstradan propslar─▒ kuralland─▒rmak, s─▒n─▒rland─▒rmak i├žin kullanaca─č─▒z. ├ľnce a┼ča─č─▒daki gibi mod├╝l├╝ y├╝kl├╝yoruz.</p> <p>npm install --save-dev prop-types<br>or<br>yarn add -D prop-types</p> <a href=""></a><h4>Step 9: API┬áDesign</h4> <p>UI librarylerinde 2 farkl─▒ API design, tasar─▒m ┼čekli vard─▒r. Birisi Traditional API yani Geleneksel API, bir di─čeri Compound API yani Bile┼čik API. Bunlar aras─▒nda ki farklar a┼ča─č─▒da ki┬ágibidir.</p> <figure><img alt="" src="*saaWKKfKtUaMCxnQa4_UWg.png"></figure><figure><img alt="" src="*c_WpyFCgnEh4erJMorUerA.png"></figure><h4>Step 10: Composition API</h4> <p>Yeni nesil UI libraryleri genellikle bu y├Ântemi kullanmay─▒ tercih ederler. Bu y├Ântem hem daha kontrol edilebilir hem de daha esnektir kullan─▒m a├ž─▒s─▒ndan.</p> <p>─░lk ├Ânce src alt─▒nda ÔÇťFieldÔÇŁ ad─▒nda bir klas├Âr ve i├žinde bir style.ts dosyas─▒ olu┼čturup a┼ča─č─▒da ki kodlar─▒ i├žinde tan─▒ml─▒yoruz.</p> <a href=""></a><p>Daha sonra bu <strong>ÔÇťFieldÔÇŁ</strong> klas├Âr├╝ i├žinde ÔÇťFieldContextÔÇŁ ad─▒n da bir context tutaca─č─▒z. Burada createContext hooksu ile context olu┼čturup form alanlar─▒nda bu contextProvider─▒n─▒ kullanaca─č─▒z.</p> <a href=""></a><p>Ve ayr─▒ca bir altta ki ÔÇťFieldÔÇŁ component─▒m─▒zda kullanaca─č─▒m─▒z unique id utilsini, utils klas├Âr├╝ alt─▒nda useUniqueID.ts dosyas─▒ i├žinde a┼ča─č─▒daki gibi olu┼čturuyoruz. Tabi ├Ânce bunu yapmam─▒z─▒ sa─člayacak olan nanoid librarysini y├╝kl├╝yoruz.</p> <p>npm install --save-dev nanoid<br>or<br>yard add -D┬ánanoid</p> <a href=""></a><p>Daha sonra yukar─▒da ki ÔÇťContextProviderÔÇŁ─▒ ÔÇťInputÔÇŁ, ÔÇťLabelÔÇŁ gibi alanlari i├žine koyaca─č─▒m─▒z bir ÔÇťField.tsxÔÇŁ tan─▒mlayaca─č─▒z.</p> <a href=""></a><p>Daha sonra ÔÇťInputÔÇŁ ve ÔÇťLabelÔÇŁ componentlar─▒m─▒z─▒ olu┼čturaca─č─▒z.</p> <a href=""></a><a href=""></a><p>Daha sonra ÔÇťInput.stories.tsxÔÇŁ ad─▒nda yeni bir story dosyas─▒ olu┼čturup asa─č─▒da ki gibi ÔÇťFieldÔÇŁ ve i├žine g├Âmd├╝─č├╝m├╝z ÔÇťInputÔÇŁ ve ÔÇťLabelÔÇŁ─▒ ├ža─č─▒rarak burada kullanabiliyor olaca─č─▒z.</p> <a href=""></a><p>Ve son olarak da gelin yine Field klas├Âr├╝ alt─▒nda bir di─čer form eleman─▒m─▒z Textarea componentimizi olu┼čtural─▒m.</p> <a href=""></a><p>Field.tsx dosyam─▒zda da gerekli alanlara a┼ča─čd─▒a ki gibi TextareaÔÇÖ─▒ ekliyoruz.</p> <a href=""></a><p>Ve son olarak da Textarea.stories.tsx dosyas─▒n─▒ olu┼čturup a┼ča─č─▒da ki kodlar─▒ g├Ânderiyoruz.</p> <a href=""></a><p>Ve art─▒k Button ve Form bile┼čenlerine sahip bir UI k├╝t├╝phanemiz haz─▒r diyebiliriz┬á:)</p> <h4>Step 11: Tests (Jest Settings)</h4> <p>─░lk ├Ânce gerekli kurulumlar─▒ a┼ča─č─▒da ki gibi yap─▒yoruz.</p> <p>npm install --save-dev jest ts-jest @types/jest react-is<br>or<br>yarn add -D jest ts-jest @types/jest react-is</p> <p>Daha sonra packaga.json i├žinde test ad─▒nda bir script olu┼čturaca─č─▒z a┼ča─č─▒da ki gibi. ┼×uana kadar olan t├╝m scriptlerimizde bu kadar┬ázaten.</p> <a href=""></a><p>Daha sonra root dizininde jest.config.js ad─▒dna dosya olu┼čturup a┼ča─č─▒da ki ayarlar─▒ i├žine yaz─▒yoruz.</p> <a href=""></a><h4>Step 12: Tests (@testing-library/react Settings)</h4> <p>Yine a┼ča─č─▒da ki kurulumlar─▒ ilk olarak ger├žekle┼čtiriyoruz.</p> <p><strong>npm install --save-dev @testing-library/react @testing-library/jest-dom<br></strong>or<br><strong>yarn add -D @testing-library/react @testing-library/jest-dom</strong></p> <p>Daha sonra <strong>ÔÇťjest-setup.tsÔÇŁ</strong> ad─▒nda dosya olu┼čturup a┼ča─č─▒da ki 2 importu i├žine g├Ânderiyoruz. Bunlarda react testleri i├žin styled-component uyumlulu─čunu ve react i├žin jest-domÔÇÖu aktif ediyor bizim┬ái├žin.</p> <a href=""></a><p>tsconfig.json i├žine de e─čer ekli de─čilse a┼ča─č─▒daki sat─▒r─▒ ekliyoruz.<br><strong> ÔÇťincludeÔÇŁ: [ÔÇťsrc/**/*ÔÇŁ, ÔÇť./jest-setup.tsÔÇŁ]</strong></p> <h4>Step 13:┬áTests</h4> <p>Daha sonra yeri size kalm─▒┼č ama ben Button component klas├Âr├╝ i├žinde Button.spec.ts ad─▒nda bir dosya olu┼čturup Button componentimizin testlerini yap─▒yoruz.</p> <a href=""></a><p>Field testleri i├žin useUniqueID ad─▒nda bir mock utilse ihtiyac─▒m olaca─č─▒ i├žin a┼ča─č─▒da ki gibi utils klas├Âr├╝ alt─▒nda, __mocks__ klas├Âr├╝ olu┼čturup i├žinde <strong>ÔÇťuseUniqueID.tsÔÇŁ</strong> ad─▒nda dosya olu┼čturup a┼ča─č─▒daki mock utili olu┼čturuyorum.</p> <a href=""></a><p>Daha sonrada <strong>ÔÇťField.spec.tsÔÇŁ</strong> ad─▒nda test dosyam─▒z─▒ olu┼čturup a┼ča─č─▒da ki testleri yaz─▒yoruz.</p> <a href=""></a><h4>Step 14: Module┬áFormats</h4> <p>Bu a┼čamada ise olu┼čturdu─čumuz ui librarymizi babel ve @rollup librarylerini kullan─▒p compressleyip dist ├ž─▒kt─▒s─▒n─▒ alaca─č─▒z.</p> <p>├ľnce a┼ča─č─▒daki gerekli libraryleri kuruyoruz.</p> <p>npm install @babel/runtime<br>npm install --save-dev @babel/preset-env @babel/preset-typescript @babel/preset-react @babel/plugin-transform-runtime babel-plugin-styled-components<br>or<br>yarn add @babel/runtime<br>yarn add -D @babel/preset-env @babel/preset-typescript @babel/preset-react @babel/plugin-transform-runtime babel-plugin-styled-components</p> <p>┼×imdide┬á.babelrc dosyas─▒ olu┼čturup a┼ča─č─▒da ki kodlar─▒ yap─▒┼čt─▒r─▒yoruz.</p> <a href=""></a><p>Ve ┼čimdide rollup paketlerini y├╝kl├╝yoruz. Bunlar build timeda kullan─▒lacak paketler oldu─ču i├žin devDependencies olarak ekleyebiliriz.</p> <p>npm install --save-dev rollup rollup-plugin-delete rollup-plugin-node-externals @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-node-resolve<br>or<br>yarn add -D rollup rollup-plugin-delete rollup-plugin-node-externals @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-node-resolve</p> <p>Ve rollup.config.js dosyas─▒ olu┼čturup a┼ča─č─▒da ki ayarlar─▒ yerle┼čtiriyoruz.</p> <a href=""></a><h4><strong>Step 15: Typescript Declarations</strong></h4> <p>Daha sonra ayarlar─▒m─▒z─▒ a┼ča─č─▒da ki gibi yap─▒yoruz.</p> <p>Bu tan─▒mlamalarla da index.d.ts gibi typescript rulelar─▒n─▒ set eden dosyalar─▒ build olarak dist ├ž─▒kt─▒ klas├Âr├╝m├╝ze kopya olarak alaca─č─▒z.</p> <p>Daha sonra <strong>ÔÇť/root/srcÔÇŁ</strong> alt─▒nda <strong>ÔÇťindex.tsÔÇŁ</strong> dosyas─▒ olu┼čturup bundle edilecek t├╝m dosyalar─▒ burada export ediyoruz.</p> <a href=""></a><p>Daha sonra package.json dosyam─▒za a┼ča─č─▒daki ÔÇťmainÔÇŁ, ÔÇťmoduleÔÇŁ ve ÔÇťsideEffectsÔÇŁ k─▒s─▒mlar─▒n─▒da ekliyoruz ve scriptlerimizin son halide a┼ča─č─▒da ki┬ágibidir.</p> <a href=""></a><p>Ve daha sonra a┼ča─č─▒da ki kodlar─▒ s─▒rayla ├žal─▒┼čt─▒r─▒p kontrol edip buildi ald─▒─č─▒m─▒z─▒ g├Âr├╝yoruz.</p> <p>npm run format<br>npm run format:lint<br>npm run┬ábuild</p> <h4>Step 16:┬áhusky</h4> <p>Husky ile ise githuba commit g├Ândermeden veya pushlamadan ├Ânceki ├žal─▒┼čmas─▒ gereken actionlar─▒ komut olarak verece─čiz. ├ľrne─čin her commit ├Ânceki eslint checki yapmas─▒n─▒ istiyorum ve e─čer eslint hatas─▒ varsa commiti kabul etmesini istemiyorum. ─░lk ├Ânce eslint hatalar─▒n─▒ giderdikten sonra tekrar gelip commit atmas─▒n─▒ ve tekrar denetleyerek hata yoksa commitini g├Ândermesini istiyorum gibi.</p> <p>─░lk ├Ânce a┼ča─č─▒da ki kodla ÔÇťhuskyÔÇŁi y├╝kl├╝yoruz.</p> <p>npm install husky --save-dev<br>or<br>yarn add -D┬áhusky</p> <p>Ve daha sorna a┼ča─č─▒da ki kodla git hookslar─▒n─▒ aktif ediyoruz.<br>npx husky┬áinstall</p> <p>Kurulumdan sonra git hookslar─▒n─▒ otomatik etkinle┼čtirmek i├žinde a┼ča─č─▒da ki kodu set ediyoruz.<br>npm set-scrpit prepare ÔÇťhusky┬áinstallÔÇŁ</p> <p>Ve ┼čimdi de pre-commit ile commitlerden ├Ânce ├žal─▒┼čt─▒r─▒lmas─▒ gereken scriptleri set ediyoruz a┼ča─č─▒da ki gibi.<br>npx husky add┬á.husky/pre-commit ÔÇťnpm run lint &amp;&amp; npm run format:lint &amp;&amp; npm run┬átestÔÇŁ</p> <p>Ve ┼čimdide push ├Ânceki olan pre-push daki k─▒sm─▒ ayarl─▒yoruz.</p> <p>npx husky add┬á.husky/pre-push ÔÇťnpm run lint &amp;&amp; npm run format:lint &amp;&amp; npm run┬átestÔÇŁ</p> <p>Ve bu kadar ┼čimdi de─či┼čiklikleri tekrar githuba pushlayabiliriz.</p> <h4>Step 17: semantic-release</h4> <p>Ve art─▒k son ad─▒mlar─▒m─▒zdan birisi olan semantic bir ┼čekilde release ├ž─▒kmaya geldik diyebiliriz. Burada yapaca─č─▒m─▒z ayarlarla semantic olarak version ve tag alabilece─čiz, change log kay─▒tlar─▒m─▒z otomatik tutulacak ve commit mesajlar─▒m─▒z─▒ daha d├╝zg├╝n bir ┼čekilde tutabilece─čiz.</p> <p>─░lk ├Ânce a┼ča─č─▒da her zaman yapt─▒─č─▒m─▒z gibi gerekli libraryleri y├╝kl├╝yoruz.</p> <p>yarn add -D semantic-release <a href="">@semantic</a>-release/changelog <a href="">@semantic</a>-release/git commitizen cz-conventional-changelog<br>or<br>npm install --save-dev semantic-release <a href="">@semantic</a>-release/changelog <a href="">@semantic</a>-release/git commitizen cz-conventional-changelog</p> <p>Sonra a┼ča─č─▒da ki release, repository alan─▒n─▒ ve yeni 2 scriptimizi package.jsona ekleyelim.</p> <a href=""></a><p>Art─▒k commitlerimizi git add yapt─▒ktan sorna npm run commit diyerek ├žal─▒┼čt─▒rd─▒ktan sonra commitizen packagenin standartlar─▒na g├Âre g├Ânderece─čiz. Ve pushlad─▒ktan sonra github actionslar semantic-release paketiyle birlikte automation i┼člemini otomatik olarak┬áyapacak.</p> <h4>Step 18: Github Environment Variable</h4> <p>├ľnce Github actionslar─▒nda kullan─▒lmak ├╝zere ilk ba┼čta NPM_TOKEN ad─▒nda bir env─▒ronment variable tan─▒mlamam─▒z gerekiyor github repomuza. Bu tokeni almak i├žin npme gidip bir tane auyomation i├žin token olu┼čturuyoruz ve a┼ča─č─▒daki gibi olu┼čturdu─čumuz ui librarysinin github reposunun ayarlar─▒nda ki Secret k─▒sm─▒nda, NPM_TOKEN name olacak ┼čekilde npmden ald─▒─č─▒m─▒z token ile burada yeni bir environment variable tan─▒ml─▒yoruz.</p> <figure><img alt="" src="*tGzH7s0-wLwt7udp0ziMDA.png"></figure><p>Github-actionslara ge├žmeden ├Ânce son olarakda ui-library olan package ismimizi unique bir npm package ismi se├žerek de─či┼čtiriyoruz. Npm k├╝t├╝phanesine girerek se├žti─činiz paket ismini kontrol edin. Ve privateyide false yap─▒yoruz ├ž├╝nk├╝ free npm ├╝yeli─čiyle private npm packageleri y├╝kleyemiyoruz. Bizimkisi de free oldu─ču i├žin public bir npm k├╝t├╝phanesi olu┼čturuyoruz.</p> <a href=""></a><h4>Step 19: Github┬áActions</h4> <p>Ve ┼čimdi t├╝m ayarlar─▒m─▒z─▒ yapt─▒─č─▒m─▒za g├Âre s─▒ra olu┼čturdu─čumuz libraryi npme publish etmeye geldi. Npm publish i┼čini github actionslarla otomatik bir ┼čekilde yapaca─č─▒z. S├╝re├ž ┼ču ┼čekilde i┼čleyecek. Biz bir commit g├Ânderdi─čimiz de yani githuba push etti─čimiz de githubda a┼ča─č─▒da yazd─▒─č─▒m─▒z ci actionu ├žal─▒┼č─▒p npm release ve semantic versioning automationunu bizim i├žin┬áyapacak.</p> <p>Bunun i├žin tek yapmam─▒z gereken a┼ča─č─▒daki dizine release veya istediginiz bir dosya ad─▒┬á.yml ┼čeklinde bir dosya olu┼čturmak ve a┼ča─čd─▒a ki kodlar─▒ oraya yazmak. Yorumlu sat─▒rdaki test k─▒sm─▒n─▒ bilerek b─▒rakt─▒m isterseniz oradaki gibi ikinci bir job daha ekleyip kullanabilirsiniz.<br><strong>/root/.github/workflows/release.yml</strong></p> <a href=""></a><img src=";referrerSource=full_rss&amp;postId=3d18a41e3e27" width="1" height="1" alt="">
NPM - Package Publishing Notes &amp; Policy
<figure><img alt="" src="*-_8rJAQ9c9JTizPGCX8Cyg.png"></figure><p>Bu sefer NPMÔÇÖde package publishing yaparken yapt─▒─č─▒m hatalar, kar┼č─▒la┼čt─▒─č─▒m sorunlar ve buldu─čum ├ž├Âz├╝mleri anlatt─▒─č─▒m bir yaz─▒ yazmak istiyorum. Asl─▒nda burada anlatacaklar─▒m─▒n bir ├žo─čunu sizde merak edip ara┼čt─▒r─▒p d├╝┼č├╝nmek ve challenge ya┼čamak zorunda kalacaks─▒n─▒z e─čer g├╝n├╝n birince bu i┼če deep dive giri┼čecek olursan─▒z.</p> <h3>Yapt─▒─č─▒m hatalar</h3> <h4>├ľzel isimle publish etmek &amp; Version numaras─▒ kullanmak</h4> <p>Diyelim ki icon-generator diye ├Âzel ve g├╝zel bir isime sahip bir library olu┼čturaca─č─▒m. Bu libraryi npmÔÇÖe direk olarak bu isimle pushlamak yerine daha s─▒radan icon-test-generator ad─▒yla g├Ândermek daha do─čru olurdu. Ve ayr─▒ca ben 1.0.0 gibi bir version numaras─▒ kullanm─▒┼čt─▒m package.json i├žinde. Buda bu ├Âzel isimle olu┼čturdu─čum packagenin bir daha asla bu version numaras─▒ ile yeniden publish edemeyece─čim anlam─▒na geliyordu. Yani e─čer olu┼čturdu─čunuz packageA k├╝t├╝phanesini npmÔÇÖe 1.0.0 version numaras─▒yla veya herhangi bir version numaras─▒ ile npmÔÇÖe g├Ânderirseniz bir daha bu packageyi npmden silseniz dahi ayn─▒ version numaras─▒ ile npme publish edemeyece─činiz anlam─▒na gelir. Yani version numaras─▒n─▒ de─či┼čip tekrar publish etmeliyiz demek oluyor bu.┬á:(</p> <h4>Test publishleri npm ├╝zerinde┬áyapmak</h4> <p>Evet buda i┼čin bir di─čer ac─▒ taraf─▒. Test publishlerimi a┼ča─č─▒daki ┼ču toolu bilene kadar hep npm ├╝zerinde yapt─▒m buda bana fazlaca maliyetli oldu nihayetinde. Siz bu hatay─▒ yapmay─▒n ve <strong>Verdaccio </strong>isimli local npm publish toolunu kullanarak olu┼čturdu─čunuz packageleri ├Ânce localde publsih edip sonu├žlar─▒n─▒ g├Âzlemleyin.</p> <h4>Alpha - Beta - RC Releaseleri Yapmamak</h4> <p>─░lla paketinizi npmÔÇÖe veya bir bulut ortam─▒na publish edecekseniz paketlerinizin ├žal─▒┼č─▒rl─▒─č─▒ndan emin olmadan ├Ânce paketlerinizi kesinlikle alpha, beta, rc gibi stabil olmayan s├╝r├╝mlerle ├ž─▒kartmal─▒s─▒n─▒z. Bu hem bu s├╝r├╝mlerin halen test edildi─čini hem baz─▒ ├Âzelliklerinin ├žal─▒┼čm─▒yor olabilece─čini anlatt─▒─č─▒ i├žin yanl─▒┼č publishlerde bu versionlarla birlikte sorun olmayacakt─▒r. Tabi ki e─čer ufak tefek buglar yoksa major problemler varsa stabil veya fix versionlar─▒ ├ž─▒kt─▒ktan sonra bu s├╝r├╝mleri unpublish yap─▒n yapam─▒yorsan─▒zda deprecated yap─▒n.</p> <p><a href="">npm-version | npm Docs</a></p> <h4>Summary</h4> <ul> <li>npmÔÇÖe sadece bir kere ayn─▒ versionu publish edebilirsiniz, unpublish etseniz dahi daha ├Ânce publish edilmi┼č bir versionu tekrar npmÔÇÖe publish edemezsiniz.</li> <li>npmÔÇÖe publish etmeden ├Ânce Verdaccio gibi local package managerlere publish┬áediniz.</li> <li>├žal─▒┼čt─▒─č─▒na tam olarak emin olmad─▒─č─▒n─▒z packageleri alpha, beta veya rc gibi s├╝r├╝m adlar─▒ ile┬á├ž─▒k─▒n─▒z.</li> </ul> <h3>Notes &amp; Important Things</h3> <ul> <li>unpublish policyÔÇÖye dikkat edin. ├ľzetle bu yaz─▒n─▒n yaz─▒ld─▒─č─▒ tarih itibari ile: (De─či┼čebilir buras─▒ bu y├╝zden documentation tavsiye edilir)<br>- ─░lk publishden 72 saat i├žinde her hangi bir zaman<br>- E─čer 72 saat ├Ânceden publish edildiyse:<br> * son hafta 300 den az download edildiyse<br> * sadece 1 tane owner veya maintainera sahipse<br> * npmdeki di─čer paketler bu pakete ba─čl─▒ de─čilse<br>unpublish edilebilir.</li> <li>Bu ┼čartlar d─▒┼č─▒ndakiler unpublish edilemez fakat profilinizde illada bu paketleri g├Ârmek istemiyorsan─▒z, npm i maintainer olarak ekleyerek kendinizide maintainerlardan ├ž─▒kartarak bu paketi npmÔÇÖe devrederek profilinizden kald─▒rabilirsiniz. B├Âylece paket yine var olur ama en az─▒ndan sizin ├╝zerinizden ve profilinizden kalkm─▒┼č┬áolur.</li> <li>Belirli bir pacakge versionunu unpublish yapmak.<br>npm unpublish packageName@version</li> <li>B├╝t├╝n packageyi unpublish yapmak. (-f force anlam─▒nda)<br>npm unpublish -f packageName@version</li> <li>NpmÔÇÖi maintainer olarak pakete eklemek:<br>npm owner add npm┬ápackage</li> <li>Paketten kendinizi maintainerlar aras─▒ndan ├ž─▒kartmak<br>npm owner rm username┬ápackage</li> <li>B├╝t├╝n bir paketi depracated yapmak.<br>npm deprecate packageName "message"</li> <li>Belirli bir paketi deprecated yapmak.<br>npm deprecate packageName@version "message"</li> </ul> <img src=";referrerSource=full_rss&amp;postId=3b7d4be9f1fb" width="1" height="1" alt="">
Semantic Versioning (Version ruleset in package.json (^,~,&gt;,&gt;=,&lt;,&lt;=,=,-,||))
<p>Node.js packageslerinde en g├╝zel ┼čey kesinlikle packageler i├žin version numaraland─▒rma s├╝r├╝mlerinde semantic versioning kullanmalar─▒ diyebiliriz.</p> <figure><img alt="" src="*eWYHDceiwMSdnHavp-DAVA.png"></figure><p>Semantic Versioning konsepti olduk├ža basittir. B├╝t├╝n version sadece 3 digit yani say─▒dan olu┼čur:┬áx.y.z.</p> <ul> <li>─░lk say─▒ yani x, major┬áversion</li> <li>─░kinci say─▒ yani y, minor┬áversion</li> <li>├ť├ž├╝nc├╝ say─▒ yani z, patch┬áversion</li> </ul> <p>Yeni bir s├╝r├╝m ├ž─▒kmak istedi─činizde istedi─činiz gibi bir say─▒y─▒ artt─▒rmazs─▒n─▒z. Baz─▒ kurallar dahilinde bu say─▒lar─▒ artt─▒r─▒r─▒z.</p> <ul> <li>APIÔÇÖda eskiye g├Âre uyumsuz ├Ânemli de─či┼čikliklerde MAJOR versionu artt─▒r─▒r─▒z</li> <li>Geriye d├Ân├╝k uyumlu bir ┼čekilde ├ž─▒kartt─▒─č─▒m─▒z yeni ├Âzellik ve functionalitylerde MINOR versionu artt─▒r─▒r─▒z</li> <li>Geriye d├Ân├╝k uyumlu bir ┼čekilde bug fixlerde veya k├╝├ž├╝k d├╝zeltmelerde veya typolarda PATCH versionu artt─▒r─▒r─▒z</li> </ul> <p>The convention is adopted all across programming languages, and it is very important that every npm package adheres to it, because the whole system depends on┬áthat.</p> <p>Bu yap─▒ b├╝t├╝n pro─čramlanma dillerinde bu ┼čekilde benimsenmi┼čtir. Ve npm packagelerininde bu kurallara ba─čl─▒ kalmas─▒ hem bizim hem de sistem i├žin ├žok ├Ânemlidir. ├ç├╝nk├╝ b├╝t├╝n sistem ucunda buna ba─čl─▒d─▒r.</p> <h4>Why is that so important?</h4> <p>├ç├╝nk├╝npm baz─▒ kurallar ayarlar ve biz bu kurallara g├Âre package versionlar─▒n─▒ ayarlar─▒z uygulamam─▒z─▒n<a href="">package.json </a>i├žinde. Ve bu packagelerimize baz─▒ ruleslar ekleriz <a href="">package.json </a>i├žinde. Bu rullara g├Âre npm update yapt─▒─č─▒m─▒zda d├╝zg├╝nce y├╝klemelerimizi ger├žekle┼čtiririz.</p> <h4>The rules use those┬ásymbols:</h4> <ul> <li>^</li> <li>~</li> <li>&gt;</li> <li>&gt;=</li> <li>&lt;</li> <li>&lt;=</li> <li>=</li> <li>-</li> <li>||</li> </ul> <h4>LetÔÇÖs see those rules in┬ádetail:</h4> <ul> <li>^: E─čer version number olarak bir packageye ^0.13.0 yazarsan─▒z npm update yapt─▒─č─▒m─▒zda e─čer bu packagenin yeni minor veya patch releasesi (0.13.1, 0.14.0gibi) payla┼č─▒lm─▒┼čsa bu payla┼č─▒lan yeni versionlar─▒ y├╝kler, e─čer yoksa yaz─▒lm─▒┼č versionu┬áy├╝kler.</li> <li>~: E─čer version number olarak bir packageye ~0.13.0 yazarsan─▒z npm update yapt─▒─č─▒m─▒zda e─čer bu packagenin yeni patch releasesi (0.13.1 gibi) payla┼č─▒lm─▒┼čsa bu payla┼č─▒lan yeni versionlar─▒ y├╝kler, e─čer yoksa yaz─▒lm─▒┼č versionu┬áy├╝kler.</li> <li>&gt;: Herhangi bir y├╝ksek versionu kabul┬áeder.</li> <li>&gt;=: Herhangi bir y├╝ksek veya e┼čit versionu kabul┬áeder</li> <li>&lt;=: Herhangi bir d├╝┼č├╝k veya e┼čit versionu kabul┬áeder</li> <li>&lt;: Herhangi bir d├╝┼č├╝k versionu kabul┬áeder.</li> <li>=: Tam olarak belirtti─čimiz versionu kabul┬áeder</li> <li>-: Belirlik bir aral─▒kta ki versionu kabul eder. Example: 2.1.0 -┬á2.6.2</li> <li>||: Birden fazla rule set ederiz pipelarla. Example: &lt; 2.1 || &gt;┬á2.6</li> </ul> <p>Yukar─▒daki formu├╝llerden bir ka├ž─▒n─▒ kullanarak kendinize ├Âzeli kurallarda ayarlayabilirziniz, for example use 1.0.0 || &gt;=1.1.0 &lt;1.2.0 to either use 1.0.0 or one release from 1.1.0 up, but lower than┬á1.2.0.</p> <p>Ba┼čka kurallarda var:</p> <ul> <li>no symbol: Her hangi bir i┼čaret koymazsak sadece belirtti─čimiz versionu y├╝klemesini istedi─čimizi s├Âyleriz. Bir nevi = i┼čareti gibi.┬á(1.2.1)</li> <li>latest: packagenin latest yani en son s├╝r├╝m├╝ hangisi ise onu kullanmak istedi─čimizi s├Âyleriz.</li> </ul> <p><a href="">About semantic versioning | npm Docs</a></p> <img src=";referrerSource=full_rss&amp;postId=372cfe9c93af" width="1" height="1" alt="">
Book me
Made with
Mucahid Yazar