Search code examples
reactjsfirebaseredux

I'm using redux and firebase for storage and I don't know what I'm doing wrong


Actions/index.js The problem is in the PostArticleAPI() function

import db, { auth, provider, storage } from "../firebase";
import { SET_USER } from "./actionType";

export const setUser = (payload) => ({
type: SET_USER,
user: payload
});

export function signInAPI() {
return (dispatch) => {
    auth.signInWithPopup(provider).then((payload) => {
        console.log(payload);
        dispatch(setUser(payload.user));
    }).catch((error) => alert(error.message));
}
}

export function getUserAuth() {
return (dispatch) => {
    auth.onAuthStateChanged(async (user) => {
        if (user) {
            dispatch(setUser(user));
        }
    })
}
}

export function signOutAPI() {
return (dispatch) => {
    auth.signOut().then(() => {
        dispatch(setUser(null));
    }).catch((error) => {
        console.error(error.message);
    });
}
}

export function postArticleAPI(payload) {
return (dispatch) => {
    if (payload.image != '') {

        const upload = storage.ref(`images/${payload.image.name}`).put(payload.image);

        upload.on('state_changed', (snapshot) => {

            const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
            console.log(`Progress: ${progress}%`);

            if (snapshot.state === 'RUNNING') {
                console.log(`Progress: ${progress}%`);
            }

        }, (error) => console.log(error.code),
            async () => {
                const downloadURL = await upload.snapshot.ref.getDownloadURL();
                db.collection('articles').add({
                    actor: {
                        description: payload.user.email,
                        title: payload.user.displayName,
                        date: payload.timestamp,
                        image: payload.user.photoURL
                    },
                    video: payload.video,
                    shareImg: downloadURL,
                    comments: 0,
                    description: payload.description,
                })
            }
        );
    }
}
}

PostModal.js

import React, { useState } from 'react'
import styled from 'styled-components';
import ReactPlayer from 'react-player';
import { connect } from 'react-redux';
import { postArticleAPI } from '../actions';
import firebase from 'firebase';

const PostModal = (props) => {
const [editorText, setEditorText] = useState('');
const [shareImage, setShareImage] = useState('');
const [videoLink, setVideoLink] = useState('');
const [assetArea, setAssetArea] = useState('');
const handleChange = (e) => {
    const image = e.target.files[0];

    if (image === '' || image === undefined) {
        alert(`not an image, the file is a ${typeof (image)}`);
        return;
    }
    setShareImage(image);

}

const switchAssetArea = (area) => {
    setShareImage("");
    setVideoLink("");
    setAssetArea(area);

};

const postArticle = (e) => {
    console.log("heyy abay");
    e.preventDefault();
    if (e.target !== e.currentTarget) {
        console.log("heyy abay2");
        return;
    }

    const payload = {
        image: shareImage,
        video: videoLink,
        user: props.user,
        description: editorText,
        timestamp: firebase.firestore.Timestamp.now(),
    }
    props.postArticle(payload);
    reset(e)
}

const reset = (e) => {
    setEditorText("");
    setShareImage("");
    setVideoLink("");
    setAssetArea("");
    props.handleClick(e);
};

return (
    <>
        {props.showModal === "open" && (
            <Container>
                <Content>
                    <Header>
                        <h2>Create a post</h2>
                        <button onClick={(e) => reset(e)}>
                            <img src="/images/cancel.svg" alt="cancel" />
                        </button>
                    </Header>
                    <SharedContent>
                        <UserInfo>
                            {props.user && props.user.photoURL ? (
                            <img src={props.user.photoURL} alt="" />) 
                            : (<img src="/images/user.svg" alt="" />)}
                            {/* <img src="/images/user.svg" alt="" /> */}
                            <span>{props.user.displayName}</span>
                        </UserInfo>

                        <Editor>
                            <textarea value={editorText}
                                onChange={(e) => setEditorText(e.target.value)}
                                placeholder='What do you want to talk about?'
                                autoFocus={true}
                            />
                            {assetArea === "image" ? (
                                <UploadImage>
                                    <input type="file"
                                        accept='image/gif, image/jpeg, image/png'
                                        name='image'
                                        id='file'
                                        style={{ display: 'none' }}
                                        onChange={handleChange}
                                    />
                                    <p>
                                        <label htmlFor="file">Select an image to share</label>
                                    </p>
                                    {shareImage && <img 
                                     src={URL.createObjectURL(shareImage)} />}

                                </UploadImage>) : (
                                assetArea === "media" && (
                                    <>
                                        <input
                                            type="text"
                                            placeholder="Please input a video link"
                                            value={videoLink}
                                            onChange={e => setVideoLink(e.target.value)}
                                        />
                                        {videoLink && (<ReactPlayer width={"100%"} 
                                        url={videoLink} />)}
                                    </>))
                            }
                        </Editor>
                    </SharedContent>
                    <ShareCreations>
                        <AttachAssets>
                            <AssetButton onClick={() => switchAssetArea("image")} >
                                <img src="/images/gallery.svg" alt="" />
                            </AssetButton>
                            <AssetButton onClick={() => switchAssetArea("media")}>
                                <img src="/images/video.svg" alt="" />
                            </AssetButton>
                        </AttachAssets>
                        <ShareComment>
                            <AssetButton>
                                <img src="/images/chat1.svg" alt="" />
                                Anyone
                            </AssetButton>
                        </ShareComment>
                        <PostButton disabled={!editorText ? true : false} 
                        onClick={(e) => postArticle(e)}>
                            Post
                        </PostButton>
                    </ShareCreations>
                </Content>
            </Container>)
        }
    </>
)
};

//I'm hiding CSS


const mapStateToProps = (state) => {
return {
    user: state.userState.user,
};
}

const mapDispatchToProps = (dispatch) => ({
postArticle: (payload) => dispatch(postArticleAPI(payload)),
});

export default connect(mapStateToProps, mapDispatchToProps)(PostModal);

Error:

TypeError: firebase__WEBPACK_IMPORTED_MODULE_0_.storage.ref is not a function

This is the error I'm getting and in this line actions/index.js

const upload = storage.ref(`images/${payload.image.name}`).put(payload.image);

It is saying storage.ref is not a function. I am getting this error that is why I'm writing this extra lines


Solution

  • You are probably not exporting properly the storage from ../firebase.

    If you share the code from that file we can help you more. Maybe it's also a missmatch with the new Firebase API version (v9) and old one (v8).