์ง๋ฌธ ์์ฑ, ์์ ํ์ด์ง ๋ฆฌํฉํ ๋ง ๋ฐ ์ด์ ์ฌํญ์ ํด๊ฒฐํ๋ค.
์ง๋ฌธ ์์ฑ, ์์ ํ์ด์ง quill editor ๋์
,
๋ฆฌ๋์ค ํดํท์ผ๋ก ๋ฆฌํฉํ ๋ง, ์ปค์๊ฐ ์์ผ๋ก ์ค๋ ์ด์๋ฅผ ํด๊ฒฐ ํ๋ค.
store, reduce๋ฑ์ ๋ฏธ๋ฆฌ ์ธํ ๋์ด ์์ด์
quill ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์นํ๊ณ
textarea๋ก ์์ฑ๋์ด ์๋ ๋ถ๋ถ์ ๋ณ๊ฒฝ๋ง ํด์ฃผ๋ฉด ๋์ ๊ธ๋ฐฉ ์ ์ฉ์ด ๋์๋ค.
<EditorContent
value={'์๋
!'}
theme='bubble'
readOnly
/>
theme: "bubble"
๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ์๋จ ํด๋ฐ๊ฐ ์ฌ๋ผ์ง๊ณ
input๊ณผ ๋์ผํ๊ฒ readonly
๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ์์ฑํ์ง ๋ชปํ๋๋ก ๋ง์์ค๋ค.
์ด๊ฑธ ํตํด ์ง๋ฌธ ๋ทฐํ์ด์ง๋ ์์ ํ๋ฉด ์ข์ ๋ฏ ์ถ๋ค.
//modules/index.js
const store = configureStore({
reducer: {
question: questionSlice.reducer,
}
});
export default store;
.
.
.
//modules/questionSlice.jsx
const initialState = {
tags: [],
}
const questionSlice = createSlice({
name: "questionSlice",
initialState,
typeTags: (state, action) => {
state.tags = [...state.tags, action.payload];
},
updateTags: (state, action) => {
state.tags = action.payload
},
checkPlusTags: (state) => {
state.checkedCount += 1
},
checkMinusTags: (state) => {
state.checkedCount -= 1
},
}
})
export const { updateTags, checkPlusTags, checkMinusTags, typeTags } = questionSlice.actions;
export default questionSlice;
์๋๋ typeTags
๋ง ์์๋๋ฐ updateTags, checkPlusTags,checkMinusTags ์ถ๊ฐํด ์ฃผ์๋ค.
action.payload
๋ ๊ฐ ํจ์์ ์ธ์๋ก ๋ค์ด์ค๋ ๊ฐ๋ค์ด๋ผ ์๊ฐํ๋ฉด ๋๋ค.
//question.jsx
import { typeTags , checkPlusTags, checkMinusTags, updateTags} from '../../modules/questionSlice';
const tags = useSelector((state) => state.question.tags);
const checkCount = useSelector(state => state.question.checkedCount)
const handlerTag = (name, description) => {
const tagSelected = tags.some((el) => el.tagName === name);
if (tagSelected) {
const updatedTags = tags.filter((el) => el.tagName !== name);
dispatch(updateTags(updatedTags));
dispatch(checkMinusTags())
} else {
const newTag = { tagName: name, tagDescription: description };
dispatch(typeTags(newTag));
dispatch(checkPlusTags())
}
};
state.question.checkedCount
์์ question
๋ store์ ์์ฑ๋ question: questionSlice.reducer
๋ผ ์๊ฐํ๋ฉด ๋๋ค.
questionํด๋น ํ์ด์ง๋
useDispatch, useSelection์ ์ด์ฉํด action.payload๋ก ์ ๋ฌ๋ ๊ฐ์ ์ธ์๋ก ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.
๋ํ ๋ค๋ฅธ ์ฝ๋์์๋ ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํด์ ๊ฐ์ ํ๋ ๋ ๋ง๋ค ํ์๊ฐ ์์๊ณ
ํ์คํ ์ด์ ์ฝ๋์ ๋น๊ตํ์ ๋ ๊ฐ๊ฒฐํด ์ก๋ค.
๊ธ ์์ฑ์ ์ปค์๊ฐ ๊ณ์ ๋งจ ์์ผ๋ก ์ด๋ํ๋ ๋ฌธ์ ๊ฐ ์์๋ค.
๋ฌธ์ ๋ title
๊ธฐ๋ณธ ๊ฐ์ด ""
๋น ๋ฌธ์์ด๋ก ๋ค์ด๊ฐ๋๋ฐ ์ด๊ฒ ๋ฌธ์ ๊ฐ ๋์๋๊ฑฐ ๊ฐ๋ค.
defaultValue={memTitle || title}
์ด๋ ๊ฒ ์กฐ๊ฑด์์ค ์์ ํ๋ค.
๋ํ value=""
๋ก ๋ฃ์ ๊ฒฝ์ฐ input text ๋ด์ฉ์ ์์ ํ ์ ์์๋ค.
์ด ๋ถ๋ถ์ defaultValue=""
์ผ๋ก ์ค์ ํด๊ฒฐ ํ ์ ์์๋ค.
const title = useSelector((state) => state.question.title);
<QInput
type='text'
placeholder='์ ๋ชฉ์ ์์ฑํด ์ฃผ์ธ์. (80์ ์ดํ)'
defaultValue={memTitle || title}
onChange={handleChange}
/>
[1,2,3]
๋ฐฐ์ด ์์ ์ซ์๋ก ์ง์ ํด ์ฃผ์
์... ์์ง ์งํํ์ง ๋ชปํ๊ณ ์๋ค.dangerouslySetInnerHTML
๋ผ๋ ์์ฑ์ ์ด์ฉํด๋ ๋์ง๋ง ๋ณด์์ ๋ฌธ์ ๊ฐ ์๋ค๊ณ ํ๋ค.๋ฐฑ์๋ ์ธก๊ณผ์ ์ํต์ด ์ํํ์ง ์์
ํ๊ทธ ์์ญ์ ์ด์๊ฐ ์๋๊ฑฐ ๊ฐ๋ค.
๋ํ OAuth ๋ถ๋ถ๋ ์์ง ๊ตฌํ ์ค์ด๋ผ๊ณ ํ์
์
๋ก๊ทธ์ธ ํ์ด์ง, ๋ก๊ทธ์ธ ๋ ๊ฒฝ์ฐ ๋ค๋ฅธ ๊ณณ๋ ์ ๋ฉด ์์ ์ด ํ์ํ ์ํฉ์ด๋ค.
ํ์ฌ 3~4์ผ ์ ๋ ๋จ์ ์ํฉ์ธ๋ฐ
๋ฐฐํฌ ๊ธฐ๊ฐ์ ์ ์ธํ๋ฉด 2์ผ ์ ๋ ๋จ์๋ค.
๊ณผ์ฐ... ์ ํ ์ ์์์ง ๊ฑฑ์ ์ด ๋๋ค.