RxFire в Svelte 3 с использованием Firebase Firestore и аутентификации

RxFire был создан Дэвидом Истом, который является Firebase Developer Advocate. Хотя Firebase Blog представил RxFire в сентябре 2018 года. Я подумал, что это будет хорошим ориентиром для новичков, начинающих работу с Svelte 3 и Firebase.Для тех, кто работает с Angular, вы можете быть знакомы с RxJS и пакетом Angularfire2. Из своего опыта я знаю, что вы ДОЛЖНЫ изучить RxJS, если собираетесь использовать Angular в приложении любого размера. Это может быть одной из самых трудных частей для изучения, но есть несколько фантастических учебников и сайтов, посвященных тому, как работает RxJS.Некоторые из моих любимых

Новичок в Svelte 3, пожалуйста, проверьте

Пример

В примере ниже показан быстрый предварительный просмотр того, как будет работать конечное приложение React. Как вы можете видеть, есть 4 основных шага, которые будут происходить.

  • Войти

  • Добавить факт о кошке

  • Показать добавленный факт о кошке в списке

  • Выйти

Установка

Вам понадобится NPM, который поставляется в комплекте с nodejs. Также проще всего установить npx, используя шаблон, предоставленный на git.

npx degit sveltejs/template rxfire-svelte cd rxfire/svelte

Вам также потребуется создать собственный проект Firebase и инициализировать базу данных Firestore, пожалуйста, создайте ее, используя строгий режим. Пример правил;

Окончательная структура приложения

Установите зависимости

Вам понадобятся rxfire, firebase и rxjs

npm i rxfire firebase rxjs

Создайте Firebase.js

Firebase.js будет нашим основным файлом Firebase и будет включать инструменты для нашего приложения firebase, включая инстанцирование firebase. Этот файл включает rxfire для вспомогательных функций auth и firestore.Firebase.js

«`plain text
import «firebase/auth»;
import «firebase/firestore»;
import firebase from «firebase/app»;
import { authState } from «rxfire/auth»;
import { collectionData } from «rxfire/firestore»;
import { filter } from «rxjs/operators»;
const app = firebase.initializeApp({
/* Разместите здесь свою конфигурацию */
});
const firestore = firebase.firestore(app); // Инициализация firestore
const auth = firebase.auth(app); // Инициализация firebase auth
const loggedIn$ = authState(auth).pipe(filter(user => !!user)); // Наблюдаемая возвращается только тогда, когда пользователь вошел в систему.
export { app, auth, firestore, collectionData, loggedIn$ };
export default firebase;




> 

    You can skip the Instructions part of the lesson if you are already familiar with Svelte 3.

## Simple Initial Component

### Remove App.svelte and replace it with the following

You can basically think of a .svelte file equal to an html file. There are a few things to note here, any styles are scoped to the current component by default, in order to get styles outside of this you can place them within something like `:global(div.flex-row)`. However (maybe best practice), I found it easier to move these from App.svelte over to `/public/global.css`;App.svelte



```plain text
<script>
    import Instructions from './components/Instructions.svelte';
    import SignIn from './components/Signin.svelte';
    import AddCat from './components/AddCat.svelte';
    import ListCatFacts from './components/ListCatFacts.svelte';
    import { loggedIn$ } from './Firebase.js'
    /* Make something more observable */
    const user = loggedIn$;
</script>
<style>
    /* :global(div.flex-row){ display: flex; justify-content: center; flex-flow: row wrap; } :global(div.flex-column){ display: flex; justify-content: center; flex-flow: column; } .max-800{ max-width: 800px; } */
</style>
<div class="flex-row">
    <div class="flex-column">
        <Instructions />
    </div>
</div>

Вход в полноэкранный режим Выход из полноэкранного режима

Создайте Instructions.svelte

Это очень простой компонент Svelte, который не принимает никаких реквизитов, он просто возвращает прямой html.components/Instructions.svelte

«простой текст

 <img src="https://res.cloudinary.com/ajonp/image/upload/w%5C_500/v1556553295/ajonp-ajonp-com/18-rxfire-svelte-cats/RxFire%5C_Svelt.webp" alt="rxfire for cats"> 

    <p> In this example we will use RxFire to Observe the Cat Facts that we add to our Firestore Database. </p> <a href="https://github.com/AJONPLLC/rxfire-react-cats">
        https://github.com/AJONPLLC/rxfire-react-cats </a>
    <ol>
        <li> Sign In <ul>
                <li>Uses Google Auth for Firebase</li>
                <li>Found in App.svelte</li>
            </ul>
        </li>
        <li> Add Cat Fact <ul>
                <li>This will use an API and Insert the facts into Firestore</li>
                <li>Found in components/AddCat.svelte</li>
            </ul>
        </li>
        <li> Firestore collection <ul>
                <li>Observing catfacts for changes, heart eyes are your facts</li>
                <li>Found in components/ListCatFacts.svelte</li>
            </ul>
        </li>
        <li> Sign Out <ul>
                <li>Observe that user is removed</li>
            </ul>
        </li>
    </ol>
Вход в полноэкранный режим Выход из полноэкранного режима



## Update collection catfacts

### Create AddCat.svelte

The first button that we are going to add is simple enough it calls an API and pushes the data returned into a firestore collection as a new document. I always like to work from top down, so first lets import AddCat.svelte into our App.svelte.

### Update App.svelte

App.svelte



```plain text
... import AddCat from './components/AddCat'; ... <SignIn user={user} /> ...

Войти в полноэкранный режим Выход из полноэкранного режима

Теперь мы передадим наш первый реквизит в AddCat, это делается просто, объявив переменную и передав ее, в нашем случае мы будем использовать const user = loggedIn$. Необходимо ли это, скорее всего нет, но я хотел показать передачу реквизита, в идеале мы могли бы просто взять его из Firebase.js.Обратите внимание на дочернюю переменную, мы можем получить доступ к этому реквизиту, определив export let user;.Функция addCatFact вызывает API, который возвращает один случайный факт о кошке из https://cat-fact.herokuapp.com. Из-за CORS мы должны передать его через прокси, но вы увидите, что мы получим значение обратно. Затем мы используем функцию деструктуризации javascript для создания нового объекта, добавив к нему catFactDate. Это позволит нам в дальнейшем сортировать факты в нашем списке в порядке убывания.Мы добавляем случайный факт о кошке в firestore и добавляем к объекту наш catFactDate. Это позволит нам позже отсортировать факты в нашем списке в порядке убывания.Здесь нам нужно обратить особое внимание на следующие вещи

  • if — блоки if просто стандартный if, который вы ожидаете.

  • $user — Подписки, если вы пришли из angular, это как async pipe.

  • on:click={addCatFact — События компонента Это похоже на события, обычно встречающиеся в html компонентах, но здесь мы передаем функцию addCatFact, просто окружая ее фигурками.

«`plain text

import { firestore } from '../Firebase';
import catFacts from '../random.js';
export let user;
const addCatFact = async () =&gt; {
    try {
        /* Gave up on the API working!!! */
        const value = catFacts[Math.floor(Math.random() * catFacts.length)];
        await firestore.collection('catfacts').add({ ...value, catFactDate: new Date() });
    }
    catch (error) { console.error(error); }
};



{#if $user}  2. Add Cat Fact  {/if} 
Вход в полноэкранный режим Выход из полноэкранного режима



Now if you try this right now it should fail with this alert

![](https://media.codingcat.dev/image/upload/v1657636585/main-codingcatdev-photo/7868ceef-45bb-4114-b3d3-bea7dbbfa2da.jpg)

This is expected as our firestore.rules are set to strict mode, we will add those after we get through our authentication section next.You may also notice in the console (and on the screen fact jumps in and out) that firebase actually adds to our array, until failing on the backend. This is done on purpose as it gives us the fast UI that we expect while still maintaining the data integrity.

## Add Firebase Authentication

### Update App.svelte

In the `SignIn` component we will again use props, we will pass the user state.App.svelte

` ... import SignIn from './components/Signin.svelte'; ...  ...  ...`



```plain text

  import firebase, { app } from '../Firebase'; /* this is like props */ export let user; const signIn = () =&gt; { const authProvider = new firebase.auth.GoogleAuthProvider(); app.auth().signInWithPopup(authProvider); }; const signOut = async () =&gt; { await firebase.auth().signOut(); };


  {#if $user}
  <h1>
    Welcome {$user.email}
    4. Sign Out
  </h1>
  {:else}
  1. Sign In {/if}

<div class="highlight"><pre class="highlight plaintext"><code>


## Update AddCat to include user uid

### Pass user to AddCat

Update our main app to pass the user prop.App.svelte

`&lt;AddCat user={user} /&gt;`

Now we can use this to include with our data going to firestore. AddCat.svelte

As well as whether or not to show the Add Cat Fact button, we check to see if the user exists. This button should only show when a user is signed in.



```plain text
&lt;div class="flex-column"&gt; {#if $user} &lt;button className="myButton" on:click="{addCatFact}"&gt; 2. Add Cat Fact &lt;/button&gt; {/if} &lt;/div&gt;

</code></pre></div>
<p></p>
<h2>
  <a name="update-firestorerules" href="#update-firestorerules">
  </a>
  Update firestore.rules
</h2>

<p></p>

<p>```plain text<br>
service cloud.firestore {<br>
    match /databases/{database}/documents {<br>
        // LockDown All<br>
        match /{document=**} {<br>
            allow read: if false; allow write: if false;<br>
        }<br>
        // User<br>
        match /users/{userId} {<br>
            allow read: if false;<br>
            allow write: if request.resource.id == request.auth.uid;<br>
        }<br>
        // CatFacts<br>
        match /catfacts/{catFactId} {<br>
            allow read: if true;<br>
            allow write: if request.auth.uid != null &amp;&amp; request.resource.data.uid == request.auth.uid;<br>
        }<br>
    }<br>
}</p>
<div class="highlight"><pre class="highlight plaintext"><code>


## Create List of Cat Facts

### Create ListCatFacts

This is probably the most important part of `RxFire` it will return an Observable that you can subscribe to for all changes to a collection by using the function `collectionData` which takes the collection as paramater as well as an option id to create, in our case we pass `catFactsRef.orderBy('catFactDate', 'desc')` and `'catFactId'`.Now we can just use a map to iterate on each catFact, whenever the Observable updates the current `catFact` state the array is updated and we can show the full list update using `{#each $catFacts as catFact}` then if you are the owner of the fact you get catheart eyes using a if block.



```plain text
&lt;script&gt;
  import { firestore } from "../Firebase";
  import catFacts from "../random.js";
  export let user;
  const addCatFact = async () =&gt; {
    try {
      /* Gave up on the API working!!! */ const value =
        catFacts[Math.floor(Math.random() * catFacts.length)];
      await firestore
        .collection("catfacts")
        .add({ ...value, catFactDate: new Date() });
    } catch (error) {
      console.error(error);
    }
  };
&lt;/script&gt;
&lt;div class="flex-column"&gt;
  {#if $user}
  &lt;button className="myButton" on:click="{addCatFact}"&gt;2. Add Cat Fact&lt;/button&gt;
  {/if}
&lt;/div&gt;

</code></pre></div>
<p></p>
Войти в полноэкранный режим Выход из полноэкранного режима

Оцените статью
devanswers.ru
Добавить комментарий