Elm ports에서 Firebase Firestore를 터치하세요!

Elm과 Firebase 기사가 절망적으로 적었기 때문에 쓰기로 결정했습니다. 특히 인증이 얽힌 기사가 없었기 때문에 좋으면 참고로 해 주세요.

이번에 한 일



이번에 한 일은 간단합니다.

Google 인증 -> 인증이 성공하면 input 가 출현 -> Firestore에서 데이터를 가져오기 input ) 다시 쓰기





JavaScript와의 상호 작용 : Ports



우선 전제 지식으로서 Firebase와 같이 JavaScript의 기본 기능이 아닌 라이브러리에서 Elm으로부터 그 자산을 사용하고 싶은 경우에는 Ports라는 구조를 사용합니다. Ports의 기본적인 사용법이나 개념에 대해서는 공식 문서을 읽는 것이 좋을 것입니다.

문서에서 중요한 부분을 꺼내 둡니다.

Elm과 JavaScript는 포트를 통해 서로 일방적으로 전송하여 통신 할 수 있습니다.

구현 해설



Ports



Elm -> JavaScript로 보내는 포트입니다.
value 는 버튼을 눌렀을 때 Google 인증을 촉구하는 부분입니다.input 는, signIn 의 요소가 재기록되었을 때에, 캐릭터 라인을 Firestore에 건네주어 포함하는 부분입니다.
port signIn : () -> Cmd msg 
port push : String -> Cmd msg

JavaScript -> Elm과 기다리는 Ports입니다.push 는 Firestore에 저장된 값(문자열)을 받습니다.input는 Google 인증이 성공할 때 read를 나타냅니다.
port read : (String -> msg) -> Sub msg
port signedIn : (Bool -> msg) -> Sub msg

ports 함수를 가지는 module는, signedIn 라고 선언해, input 와 JavaScript로부터 액션을 할 필요가 있는 함수는 exposing(공개) 할 필요가 있습니다.
port module Main exposing
    (...
    , read
    , signedIn
    , ...
    )

자바스크립트에서 기다리다


port module 함수에서 기다려야 합니다. 여러 번 기다리는 경우는 Sub.batch 에 리스트 형식으로 건네줍니다.
type Msg
    = SignIn
    | Push String
    | Read String
    | SignedIn Bool

subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.batch [ signedIn SignedIn, read Read ]

update에서는 받고 세트 하면 됩니다.
type alias Model =
    { pushText : String
    , isSignedIn : Bool
    }

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ...
        SignedIn isSignedIn ->
            ( { model | isSignedIn = isSignedIn }, Cmd.none )

        Read text ->
            ( { model | pushText = text }, Cmd.none )
        ...

-- Modelはinput要素の出し分けやinputの値に使われます。
view : Model -> Html Msg
view { pushText, isSignedIn } =
    div [ class "container" ]
        [ button [ onClick SignIn ] [ text "Google サインイン" ]
        , if isSignedIn then
            input [ type_ "input", value pushText, onInput Push ] []

          else
            text ""
        ]

Elm에서 JavaScript로 메시지 보내기



방금 선언한 ports 함수를 호출하면 됩니다. 값을 반드시 건네주지 않으면 안 되기 (위해)때문에, JavaScript -> Elm (은)는 하늘의 튜플(Unit)을 건네주고 있습니다.
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ...
        SignIn ->
            ( model, signIn () )

        Push text ->
            ( { model | pushText = text }, push text )
        ...

Elm 및 Firebase 초기 설정



여기가 Firebase와 Elm의 초기 설정입니다. subscriptions 라고 써 있으면 Elm에 관한 호출. signIn 라고 쓰여져 있으면 Firebase에 관련되는 호출(인증등). app. 라고 쓰여졌다면 Firestore에 대한 호출임을 명심하십시오.
const app = Elm.Main.init();

const config = {
  /* firebase config */
};
firebase.initializeApp(config);
const provider = new firebase.auth.GoogleAuthProvider();
const DB = firebase.firestore();

Elm에서 기다리다



Elm에서 값을 받으세요. 매우 간단합니다. firebase. 라는 형태로 되어 있을 뿐입니다.
DB. 는 Google 인증을 합니다.app.ports.[定義したports関数].subscribe([Elmから投げられた値] => {}); 는 Firestore에 값을 입력합니다.
// ログイン監視
app.ports.signIn.subscribe(_ => {
  firebase.auth().signInWithPopup(provider).then((_) => {}).catch((error) => {});
});

app.ports.push.subscribe(text => {
  const user = firebase.auth().currentUser;
  DB.collection('foo').doc(user.uid).set({input: text});
});

JavaScript에서 Elm으로 메시지 보내기



또한 간단합니다. signIn 입니다. 설명 불필요하네요. 어느 쪽이든, Firebase의 지식이 간입니다. onAuthStateChanged에서 로그인이 성공(user가 있는)했을 때, Firestore의 push 콜백으로 send 하는 것이 포인트입니다.
// ログイン監視
firebase.auth().onAuthStateChanged((user) => {
  if (user) {
    app.ports.signedIn.send(true);

    // ログイン後にDatabase監視
    DB.collection('foo').doc(user.uid).onSnapshot((doc) => {
        const data = doc.data();
        app.ports.read.send(data.input);
    });
  }
});

소스 코드 전체



여기에 소스 코드가 있습니다. 통과하여 이미지를 부풀리십시오.

요약



Elm과 JavaScript가 통신하려면 메시지를 일방적으로 보내는 것이 포인트입니다. 그 이미지가 잡히면 Firebase에서도 다른 JavaScript 라이브러리에서도 요령은 같습니다. Elm측은 형 안전이나 기술의 단순함을 살리면서, JavaScript 밖에 할 수 없는 일을 동동 밀어 넣어 리치인 어플리케이션을 만들어 봅시다!

좋은 웹페이지 즐겨찾기