[MONDEUK開発7~12日目①]執筆機能を実現

14748 ワード

💡 緒論


最近ブログ開発ログをきちんと書いていません.
理由は….個人は多くの苦しい仕事を経験した.ははは
だから開発の面でも大きな障害を受け、人も低迷に陥った.
もちろん最后に、すぐに解决しましたが!!
現在、低迷は予想されません:)
だからこの間はちゃんと開発していなかったことを今回書きます.

🔍 本題


まず書くスキルです
実際にはXSSの攻撃を予防するために仕事が必要です
まず機能を実現する目標を設定したので、本当に機能を実現しました!
書く上では、大きく分けて以下の点があります.
  • タイトル->入力title
  • コンテンツ->入力body
  • ラベルを入力->Tags
  • ボタン->機能を作成およびキャンセルします.
  • そして、それぞれの値を動作発生時のWriteReducerとして処理して状態管理を行う.

    1~2. Components/ WriteForm.js(styled-connts省略)


    まずは書く部分!
    まずここでは簡単な伝達値を設定します.
    const WriteForm = ({ onChangeText, title, body }) => {
        const onChange = (e) => {
            const { name, value } = e.target;
            onChangeText({name, value});
        };
        return (
            <>
                <StyledTitleText onChange={onChange} name="title" value={title} />
                <StyledBodyText onChange={onChange} name="body" value={body} text/>
            </>
        );
    };
    
    export default WriteForm;

    2. Components/ TagBar.js


    2つ目はラベルを渡すTagBarです
    ここはちょっと複雑で、
    まず、Tagの生成において、全体Tagsの生成を継続する現象が現れる.
    これは、関数が再レンダリングされ続けるためです.そこで、関数が再レンダリングされないようにuseCallbackを作成しました.
    まだ詳細なデザインはありませんが、クリック時にラベルを削除する機能が追加されました!
    const TagBar = ({ onChangeTags, tags }) => {
        const [ input, setInput ] = useState('');
        const [ nowTags, setNowTags ] = useState([]);
        
        const insertTag = useCallback(
            tag => {
                if ((!tag) || (nowTags.includes(tag))) return;
    
                const addedTag = [...nowTags, tag];
                setNowTags(addedTag);
                onChangeTags(addedTag);
    
            },
            [onChangeTags, nowTags]);
    
        const onChange = useCallback(e => {
            setInput(e.target.value);
        },[]);
    
        const onSubmit = useCallback(e => {
            e.preventDefault();
            insertTag(input.trim());
            setInput('');
        },[input, insertTag]);
    
        const onRemove = useCallback(
            tag => {
                const filteredTags = nowTags.filter(now => now !== tag);
                setNowTags(filteredTags);
                onChangeTags(filteredTags);
            }, [onChangeTags, nowTags]
        )
    
        return (
            <StyledTagBar>
                <StyledTagsForm onSubmit={onSubmit}>
                    <StyledTagsInput onChange={onChange} value={input} />
                    <StyledTagsBtn type="submit">등록</StyledTagsBtn>
                </StyledTagsForm>
                <TagsWrapper tags={nowTags} onRemove={onRemove}></TagsWrapper>
            </StyledTagBar>
        );
    };
    
    export default TagBar;

    3. Components/PostDiaryBtnsWrapper.js

    const PostDiaryBtnsWrapper = ({ onPostDairy, onCancel }) => {
        return (
            <StyledPostDiaryBtnsWrapper>
                <StyledPostDiaryBtn onClick={onPostDiary}>일기 올리기</StyledPostDiaryBtn>
                <StyledPostDiaryBtn onClick={onCancel}>작성 취소</StyledPostDiaryBtn>
            </StyledPostDiaryBtnsWrapper>
        );
    };
    
    export default PostDiaryBtnsWrapper;
    日記帳をアップロードするためのボタンは簡単です.ステータス値がcontainerからmoduleまで取得されると、その実現機能は終了する.containerは、全体としてactiondispatchに変換した後、サブアセンブリに変換する.

    containers/ WriteFormContainer.js

    import React, { useCallback, useEffect } from 'react'
    import { useDispatch } from 'react-redux';
    import { useSelector } from 'react-redux';
    import WriteBackground from '../../../components/write/WriteBackground';
    import WriteForm from '../../../components/write/WriteForm';
    import { changeText, initializeDiary } from '../../../modules/write';
    
    function WriteFormContainer() {
        const { title, body } = useSelector(({ writeReducer }) => ({
            title: writeReducer.title,
            body: writeReducer.body
        }));
        const dispatch = useDispatch();
        const onChangeText = useCallback(payload => dispatch(changeText(payload)),[dispatch]);
        useEffect(() => {
            dispatch(initializeDiary());
        }, [dispatch])
        return (
            <>
                <WriteBackground>
                    <WriteForm onChangeText={onChangeText} title={title} body={body}></WriteForm>
                </WriteBackground>
            </>
        )
    }
    
    export default WriteFormContainer
    
    

    containers/ TagBarContainer.js

    import React from 'react'
    import { useSelector, useDispatch } from 'react-redux';
    import TagBar from '../../../components/write/TagBar';
    import { changeText } from '../../../modules/write';
    
    function TagBarContainer() {
        const dispatch = useDispatch();
        const tags = useSelector(({writeReducer}) => ({tags: writeReducer.tags}));
    
        const onChangeTags = tags => {
            dispatch(changeText({ name: "tags", value: tags }));
        }
            
    
        return (
            <TagBar onChangeTags={onChangeTags} tags={tags} />
        )
    }
    
    export default TagBarContainer
    

    containers/ PostDiaryBtnsWrapperContainer.js

    import React, { useEffect } from 'react';
    import { useSelector, useDispatch } from 'react-redux';
    import { withRouter } from 'react-router';
    import PostDiaryBtnsWrapper from '../../../components/write/PostDiaryBtnsWrapper';
    import { writeDiary } from '../../../modules/write';
    
    function PostDiaryBtnsWrapperContainer({ history }) {
        const dispatch = useDispatch();
        const { title, body, tags, diary, writeError } = useSelector(({ writeReducer }) => ({
            title: writeReducer.title,
            body: writeReducer.body,
            tags: writeReducer.tags,
            diary: writeReducer.diary,
            writeError: writeReducer.writeError
        }))
    
        const onPostDiary = () => {
            dispatch(writeDiary({title, body, tags}))
        };
    
        const onCancel = () => {
            history.goBack();
        };
    
        useEffect(() => {
            if (writeError) console.error(writeError)
            if (diary) {
                console.log(diary)
                const { _id, author } = diary;
                console.log(author);
                history.push(`/@${author.userId}/${_id}`);
            };
        }, [writeError, diary, history])
        return (
            <PostDiaryBtnsWrapper onPostDiary={onPostDiary} onCancel={onCancel}/>
        )
    }
    
    export default withRouter(PostDiaryBtnsWrapperContainer)
    
    最後はmodule!

    module/diary.js

    import { createAction, handleActions } from 'redux-actions';
    import createActionTypes from '../lib/createActionTypes';
    import createSaga from '../lib/createSaga';
    import writeAPI from '../lib/routes/post/write';
    import {takeLatest} from 'redux-saga/effects';
    
    const CHANGE_TEXT = 'write/CHANGE_TEXT';
    const INITIALIZE_DIARY = 'write/INITIALIZE_DIARY';
    const WRITE_DIARY = 'write/WRITE_DIARY';
    const [ WRITE_DIARY_SUCCESS, WRITE_DIARY_FAILURE ] = createActionTypes(WRITE_DIARY);
    
    export const changeText = createAction(CHANGE_TEXT, ({ name, value }) => ({
        name,
        value,
    }));
    
    export const initializeDiary = createAction(INITIALIZE_DIARY, diary => diary)
    export const writeDiary = createAction(WRITE_DIARY, ({ title, body, tags }) => ({
        title, // diary title
        body, // diary content
        tags, // diary tags
    }));
    
    const writeDiarySaga =  createSaga(WRITE_DIARY, writeAPI);
    
    export function* writeSaga() {
        yield takeLatest(WRITE_DIARY, writeDiarySaga);
    }
    
    const initialState = {
        title: '',
        body: '',
        tags: [],
        writeError: '',
        diary: '',
    };
    
    const writeReducer = handleActions({
        [CHANGE_TEXT]: (state, { payload: {name, value} }) => ({
            ...state,
            [name]: value
        }),
        [INITIALIZE_DIARY]: state => initialState,
        [WRITE_DIARY]: state => ({
            ...state,
            diary: null,
            writeError: null,
        }),
        [WRITE_DIARY_SUCCESS]: (state, { payload: diary }) => ({
            ...state,
            diary,
        }),
        [WRITE_DIARY_FAILURE]: (state, { payload: writeError }) => ({
            ...state,
            writeError,
        })
    }, initialState)
    
    
    export default writeReducer
    このようにした結果.

    とても美しい(??)デザインのライティング機能が完成~
    実は、useCallbackmapのため、私は自分が2日連続で髪を結っていたことを覚えています.
    でも結局は機能を実現してこそ意味があるんですね~😁👍👏
    話が戻る.溜まった日記がいつ書けるか心配です.😂😂😂