ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Social Media 만들기 - 10)Status, create post 창 만들기
    NODE.JS 2021. 7. 10. 19:44

    home 화면에 post, status가 보이도록 설정하자 .

    import React from 'react'
    import { useSelector } from 'react-redux'
    import Header from '../component/Haader'
    import Status from '../component/Status'
    import Post from '../component/Post'
    
    function HomePage(props) {
        const userLogin = useSelector(state => state.userLogin)
        const userInfo = userLogin
    
        if(!userInfo){
            props.history.push('/login')
        }
        return (
            <div className="home row mx-0">
                <div className="col-md-8">
                    <Status/>
                    <Post />
                </div>
                <div className="col-md-4">
    
                </div>
            </div>
        )
    }
    
    export default HomePage

     

     

    post, status.js component들을 만들어준다. 

     

    status.js

    import React from 'react'
    import { useDispatch, useSelector } from 'react-redux'
    import { STATUS } from '../_constants/globalConstants'
    import Avatar from './Avatar'
    
    function Status() {
        const userLogin = useSelector(state => state.userLogin)
        const {userInfo} = userLogin
    
        const dispatch = useDispatch()
    
        return (
            <div className="status my-3 d-flex">
                <Avatar src={userInfo.user.avatar} size="big-avatar"/>
    
                <button className="statusBtn flex-fill" onClick={()=>dispatch({type:STATUS, payload:true})}>
                    {userInfo.user.username}, what are you thinking?
                </button>
            </div>
        )
    }
    
    export default Status

     

    status라는 새로운 상수, 리듀서를 만들어서 status값에 따라서 post를 생성하는 창이 뜨도록 설정하자. 

     

    globalConstants.js

    export const STATUS = 'STATUS'

     

    새로운 statusReducer를 생성해준다. 

    import { STATUS } from "../_constants/globalConstants";
    
    export const statusReducer  = (state=false, action)=>{
        switch(action.type){
            case STATUS:
                return action.payload
            default:
                return state
        }
    }

     

    store.js에 추가해준다. 

        status:statusReducer,

     

    app.js에 만약 status스토어가 true라면 화면에 StatusModal이 뜨도록 설정하자. 

    App.js

      const status = useSelector(state => state.status)
      return (
        <BrowserRouter>
          <input type="checkbox" id="theme"/>
          <div className="App">
            <div className="main">
              {userInfo && <Header/>}
              {status && <StatusModal/>}

    StatusModal을 작성하자. 

    여기서는 포스트를 업로드하는 컴포넌트를 만들 것이다. 

    캡쳐된 화면을 저장하는캔버스를 만드록, 화면을 저장하고,저장된 화면의 URL로 변환해서 저장된 화면을 이미지목록에 추가해준다. 

    import React, { useRef, useState } from 'react'
    import { useDispatch, useSelector } from 'react-redux'
    import { ALERT, STATUS } from '../_constants/globalConstants'
    import Alert from './Alert'
    
    function StatusModal() {
    
        const userLogin = useSelector(state => state.userLogin)
        const {userInfo} = userLogin
        const theme = useSelector(state => state.theme)
    
        const [content, setcontent] = useState('')
        const dispatch = useDispatch()
    
        const [Images, setImages] = useState([])
        const [stream, setStream] = useState(false)
        const [tracks, setTracks] = useState('')
    
        const videoRef = useRef()
        const canvasRef = useRef()
        
    
        const handleChangeImages=(e)=>{
            const files = [...e.target.files]
            let newImages= []
            let err = ''
    
            files.forEach(file=>{
                if(!file) return err = "File doesn't exist."
                if(file.type !== 'image/jpeg' && file.type !=='image/png'){
                    return err = "Image format is incorrect."
                }
                return newImages.push(file)
            })
    
            if(err) dispatch({type:ALERT, payload:{error:err}})
    
            setImages([...Images, ...newImages])
            
        }
    
        const deleteImage=(index)=>{
            const newArr = [...Images]
            newArr.splice(index, 1)
            setImages(newArr)
        }
    
        const handleStream= () =>{
            setStream(true)
            // navigator.getWebcam = (navigator.getUserMedia || navigator.webKitGetUserMedia || navigator.moxGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
            if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia){
                navigator.mediaDevices.getUserMedia({video:true})
                                        .then(mediastream=>{
                                            videoRef.current.srcObject = mediastream
                                            videoRef.current.play()
                                            const track = mediastream.getTracks()
                                            setTracks(track[0])
                                        }).catch(err=>console.log(err))
            }
            // else{
            //     navigator.getWebcam({video:true},
            //                     function(stream){
            //                         videoRef.current.srcObject = stream
            //                         videoRef.current.play()
            //                         const track = stream.getTracks()
            //                         setTracks(track[0])
            //                     }, function(){
            //                         console.log("Web cam is not accesible.")
            //                     })
            // }
        }
    
        const handleCapture= () =>{
            const width = videoRef.current.clientWidth;
            const height = videoRef.current.clientHeight;
    
            canvasRef.current.setAttribute("width", width)
            canvasRef.current.setAttribute("height", height)
    
            const ctx = canvasRef.current.getContext('2d')
            ctx.drawImage(videoRef.current, 0, 0, width, height)
            let URL = canvasRef.current.toDataURL()
            setImages([...Images, {camera: URL}])
        }
    
        const handleStopStream= () =>{
            tracks.stop()
            setStream(false)
        }
    
        return (
            <div className="status_modal">
                <form>
                    <div className="status_header">
                        <h5 className="m-0">Create Post</h5>
                        <span onClick={()=>dispatch({type:STATUS, payload:false})}>&times;</span>
                    </div>
    
                    <div className="status_body">
                        <textarea name="content" value = {content} placeholder={`${userInfo.user.username}, what are you thinking?`} onChange={(e)=>setcontent(e.target.value)} />
    
                        <div className="show_images">
                            {
                                Images && Images.map((image, index)=>(
                                    <div key={index} id="file_img">
                                        <img src={image.camera? image.camera : URL.createObjectURL(image)} 
                                        alt="images" className="img-thumbnail rounded" style={{filter:theme? 'invert(1)':'inver(0)'}} />
                                        <span onClick={()=>deleteImage(index)}>&times;</span>
                                    </div>
                                ))
                            }
                        </div>
    
                        {
                            stream &&
                            <div className="stream position-relative">
                                <video autoPlay muted  style={{filter:theme? 'invert(1)':'inver(0)'}} ref={videoRef} width='100%' height='100%'></video>
                                <span onClick={handleStopStream}>&times;</span>
                                <canvas ref={canvasRef} style={{display:'none'}}></canvas>
                            </div>
    
                        }
                        <div className="input_images">
                            {
                                stream
                                ? <i className="fas fa-camera" onClick={handleCapture}></i>
                                : <>
                                    <i className="fas fa-camera" onClick={handleStream}></i>
                                    <div className="file_upload">
                                        <i className="fas fa-image"></i>
                                        <input type="file" name="file" id="file_up" multiple accept="image/*" onChange={handleChangeImages}/>
                                    </div>
                                </>
                            }
                        </div>
                    </div>
    
                    <div className="statue_footer">
                    <button className="btn btn-secondary w-100" type="submit">Post</button>
                    </div>
    
                </form>
            </div>
        )
    }
    
    export default StatusModal

     

    만약 카메라가 작동하지 않는다면, 

    https://stackoverflow.com/questions/37315361/chrome-navigator-mediadevices-getusermedia-is-not-a-function

     

    Chrome: navigator.mediaDevices.getUserMedia is not a function

    I'm on localhost and trying to use the MediaDevices.getUserMedia method in Chrome. I receive the error as titled. I understand that in Chrome it is only possible to use this function with a secure ...

    stackoverflow.com

    여길 참고해보자. 

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

Designed by Tistory.