React.js如何限制单组问卷列表渲染的问题数量最多为4个
React问卷应用实现方案
需求描述
- 用户点击创建按钮即可生成一道附带4个选项的问卷问题
- 单个问卷列表最多容纳4个问题,最少保留1个问题
- 已有4个问题的列表中新增问题时,自动创建新的问卷列表
原有代码梳理
Survey.js
import React, { useState, useEffect } from "react"; import { Fragment } from "react"; import "./Survey.css"; import CreateSurvey from "../modals/CreateSurvey"; import Card from "../card/Card"; const Survey = () => { const [modal, setModal] = useState(false); const [surveyList, setSurveyList] = useState([]); useEffect(() => { let arr = localStorage.getItem("surveyList"); if (arr) { let obj = JSON.parse(arr); setSurveyList(obj); } }, []); const deleteSurvey = (index) => { let tempList = surveyList; tempList.splice(index, 1); localStorage.setItem("surveyList", JSON.stringify(tempList)); setSurveyList(tempList); window.location.reload(); }; const toggle = () => { setModal(!modal); }; const updateListArray = (obj, index) => { let tempList = surveyList; tempList[index] = obj; localStorage.setItem("surveyList", JSON.stringify(tempList)); setSurveyList(tempList); window.location.reload(); }; const saveSurvey = (surveyObj) => { let tempList = surveyList; tempList.push(surveyObj); localStorage.setItem("surveyList", JSON.stringify(tempList)); setSurveyList(surveyList); setModal(false); }; return ( <Fragment> <div className="header text-center"> <h5>问卷</h5> <button className="btn btn-primary" onClick={() => setModal(true)}> 创建问卷 </button> </div> <div className="survey-container"> {surveyList && surveyList.map((obj, index) => ( <Card surveyObj={obj} index={index} deleteSurvey={deleteSurvey} updateListArray={updateListArray} > <input type="radio" name="answerOne" /> </Card> ))} </div> <CreateSurvey toggle={toggle} modal={modal} save={saveSurvey} /> </Fragment> ); }; export default Survey;
Card.js
import React, { useState } from "react"; import "./Card.css"; import EditSurvey from "../modals/EditSurvey"; const Card = ({ surveyObj, deleteSurvey, index, updateListArray }) => { const [modal, setModal] = useState(false); const toggle = () => { setModal(!modal); }; const updateSurvey = (obj) => { updateListArray(obj, index); }; const deleteHandler = () => { deleteSurvey(index); }; return ( <div> <div className="card-wrapper mr-5"> <div className="card-top"></div> <div className="survey-holder"> <span className="card-headers">{surveyObj.name}</span> <span className="check"> <input type="radio" className="radio" /> <p className="answer"> {surveyObj.answerOne}</p> </span> <span className="check"> <input type="radio" className="radio" /> <p className="answer"> {surveyObj.answerTwo}</p> </span> <span className="check"> <input type="radio" className="radio" /> <p className="answer"> {surveyObj.answerThree}</p> </span> <span className="check"> <input type="radio" className="radio" /> <p className="answer"> {surveyObj.answerFour}</p> </span> <div className="icons"> <i className="far fa-edit edit" onClick={() => setModal(true)}></i> <i className="fas fa-trash-alt delete" onClick={deleteHandler}></i> </div> </div> <EditSurvey modal={modal} toggle={toggle} updateSurvey={updateSurvey} surveyObj={surveyObj} /> </div> </div> ); }; export default Card;
CreateSurvey.js
import React, { useState } from "react"; import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap"; import { Fragment } from "react"; const CreateSurvey = ({ modal, toggle, save }) => { const [question, setQuestion] = useState(""); const [answerOne, setAnswerOne] = useState(""); const [answerTwo, setAnswerTwo] = useState(""); const [answerThree, setAnswerThree] = useState(""); const [answerFour, setAnswerFour] = useState(""); const changeHandler = (e) => { const { name, value } = e.target; if (name === "question") { setQuestion(value); } else if (name === "answerOne") { setAnswerOne(value); } else if (name === "answerTwo") { setAnswerTwo(value); } else if (name === "answerThree") { setAnswerThree(value); } else { setAnswerFour(value); } }; const saveHandler = (e) => { e.preventDefault(); let surveyObj = {}; surveyObj["name"] = question; surveyObj["answerOne"] = answerOne; surveyObj["answerTwo"] = answerTwo; surveyObj["answerThree"] = answerThree; surveyObj["answerFour"] = answerFour; save(surveyObj); }; return ( <Fragment> <Modal isOpen={modal} toggle={toggle}> <ModalHeader toggle={toggle}>创建问卷问题</ModalHeader> <ModalBody> <form> <div> <div className="form-group"> <label>问卷问题</label> <input type="text" className="form-control" value={question} name="question" onChange={changeHandler} /> </div> </div> <div className="mt-2"> <label>问卷选项</label> <div className="form-group"> <label>选项1</label> <input type="text" className="form-control mt-2 mb-2" value={answerOne} name="answerOne" onChange={changeHandler} /> </div> <div className="form-group"> <label>选项2</label> <input type="text" className="form-control mt-2 mb-2" value={answerTwo} name="answerTwo" onChange={changeHandler} /> </div> <div className="form-group"> <label>选项3</label> <input type="text" className="form-control mt-2 mb-2" value={answerThree} name="answerThree" onChange={changeHandler} /> </div> <div className="form-group"> <label>选项4</label> <input type="text" className="form-control mt-2 mb-2" value={answerFour} name="answerFour" onChange={changeHandler} /> </div> </div> </form> </ModalBody> <ModalFooter> <Button color="primary" onClick={saveHandler}> 创建 </Button> <Button color="secondary" onClick={toggle}> 取消 </Button> </ModalFooter> </Modal> </Fragment> ); }; export default CreateSurvey;
自动分组功能修改实现
原有代码采用一维数组存储所有问题,无法满足分组要求,仅需修改Survey.js逻辑即可,其他文件无需改动:
// 修改后的Survey.js import React, { useState, useEffect } from "react"; import { Fragment } from "react"; import "./Survey.css"; import CreateSurvey from "../modals/CreateSurvey"; import Card from "../card/Card"; const Survey = () => { const [modal, setModal] = useState(false); // 改为二维数组存储,每个子数组对应一个问卷列表 const [surveyGroups, setSurveyGroups] = useState([[]]); useEffect(() => { let arr = localStorage.getItem("surveyGroups"); if (arr) { let obj = JSON.parse(arr); setSurveyGroups(obj); } }, []); const toggle = () => { setModal(!modal); }; const saveSurvey = (surveyObj) => { let tempGroups = JSON.parse(JSON.stringify(surveyGroups)); const lastGroup = tempGroups[tempGroups.length - 1]; if(lastGroup.length < 4) { // 最后一个分组未满则直接添加 lastGroup.push(surveyObj); } else { // 最后一个分组已满则新建分组 tempGroups.push([surveyObj]); } localStorage.setItem("surveyGroups", JSON.stringify(tempGroups)); setSurveyGroups(tempGroups); setModal(false); }; const deleteSurvey = (groupIndex, questionIndex) => { let tempGroups = JSON.parse(JSON.stringify(surveyGroups)); tempGroups[groupIndex].splice(questionIndex, 1); // 删完如果分组为空且不是最后一个分组,就删除空分组 if(tempGroups[groupIndex].length === 0 && tempGroups.length > 1) { tempGroups.splice(groupIndex, 1); } localStorage.setItem("surveyGroups", JSON.stringify(tempGroups)); setSurveyGroups(tempGroups); window.location.reload(); }; const updateListArray = (obj, groupIndex, questionIndex) => { let tempGroups = JSON.parse(JSON.stringify(surveyGroups)); tempGroups[groupIndex][questionIndex] = obj; localStorage.setItem("surveyGroups", JSON.stringify(tempGroups)); setSurveyGroups(tempGroups); window.location.reload(); }; return ( <Fragment> <div className="header text-center"> <h5>问卷</h5> <button className="btn btn-primary" onClick={() => setModal(true)}> 创建问卷 </button> </div> <div className="survey-container"> {surveyGroups && surveyGroups.map((group, groupIndex) => ( <div key={groupIndex} className="survey-group" style={{marginBottom: '30px'}}> <h6>问卷列表 {groupIndex + 1}</h6> <div className="group-cards" style={{display: 'flex', gap: '20px', flexWrap: 'wrap'}}> {group.map((obj, questionIndex) => ( <Card key={questionIndex} surveyObj={obj} index={questionIndex} deleteSurvey={(index) => deleteSurvey(groupIndex, index)} updateListArray={(obj, index) => updateListArray(obj, groupIndex, index)} > <input type="radio" name={`answer_${groupIndex}_${questionIndex}`} /> </Card> ))} </div> </div> ))} </div> <CreateSurvey toggle={toggle} modal={modal} save={saveSurvey} /> </Fragment> ); }; export default Survey;
内容的提问来源于stack exchange,提问作者sud
相关产品推荐
相关产品推荐

