【发布时间】:2021-02-06 01:19:23
【问题描述】:
我有一个带有下拉菜单的输入表单,我正在尝试设置默认值。该值是从父组件传递下来的,并且是从异步函数(我认为可能有一部分)接收的。 async 函数在 h1 中呈现用户名并正确显示在表单上方。它还作为根据人名确定默认值的条件。我曾尝试在多个组件中使用状态,但总是以“错误:重新渲染过多。 React 限制了渲染的数量以防止无限循环。”请看下面并帮助我弄清楚,如果您能提供一些关于我在这里缺少的概念的主题,我们将不胜感激。
const dashboard = (props)=>{
const getName = async ()=>{
try{~GETS DATA~
setName(parsedData[0].user_name}
catch{error}
}
let defaultSchool
//switch statement chooses the value for the default in dropdown menu based on the name from GET
switch(name){
case "user1":
defaultSchool= "Cool School"
case "user2":
defaultSchool= "Another School
}
return(
<div>
<InputForm defaultSchool= defaultSchool />
</div>
)
}
上面是父组件,它将这些数据向下传递到包含输入表单的下一个组件。
const InputForm = ({defaultSchool})=>{
const [school, setSchool]= useState(defaultSchool)
const [some_state, setSome_State] = useState("")
// numerous other states associated with the form with no significant relevance
const onSubmitForm = async e => {
e.preventDefault()
try{~normally POSTS data~}
catch{error}
}
return(
<h1 className="text-center my-5 input
title">Input Form</h1>
<form className="mt-5" onSubmit={onSubmitForm}>
{/* DATE */}
<input type="date" name="connection_date"
placeholder="Date of Contact"
className="form-control"
value={connection_date}
onChange={e => setDate(e.target.value)}/>
{/* SCHOOL */}
<select type="text" name="school"
placeholder="School" className="form-control mt-3"
defaultValue={defaultSchool} value={defaultSchool}
onChange={e => setSchool(e.target.value)}>
// <option value="NADA" disabled>Choose your school</option>
// this is a default option i tried with defaultValue to stop the first
value in the dropdown from showing which was unsuccessful also
to show but didn't work at all either
<option value="Cool School"> Cool School </option>
<option value="Another School">Another School </option>
<button className="btn btn-success btn-block mt-3 mb-5">Add</button>
</form>
)
}
最初,默认学校显示为下拉列表中的选定项目;我点击添加按钮,学校没有提交。但是,在第一次单击添加按钮后,会发生正确的行为,并且每次单击都会提交学校。关于这个问题有很多 SO 帖子,但没有一个包含 React 和钩子,也没有提供任何关于有条件地呈现下拉列表默认选项的见解。
完整的代码示例:
import React, { Fragment, useState, useEffect } from 'react'
//components
import InputConnection from './connectionlist/InputConnection'
import ListConnections from './connectionlist/ListConnections'
import LogoutBtn from './LogoutBtn'
import ReportingLayout from './reporting/Layout/ReportingLayout'
const Dashboard = ({ setAuth }) => {
const [name, setName] = useState("")
const [allConnections, setAllConnections] = useState([])
const [connectionsChange, setConnectionsChange] = useState(false)
const [timeDay, setTimeDay] = useState("Good Morning,")
const auth = setAuth
const getName = async () => {
try {
const response = await fetch("/dashboard/", {
method:"GET",
headers:{ token: localStorage.token }
})
const parseData = await response.json()
// console.log(parseData)
if (parseData.admin === 'lead') {
setName("Lead School Counselor")
setAllConnections(parseData.results)
}else{
setName(parseData[0].user_name)
setAllConnections(parseData)
}
} catch (error) {
}
}
const greeting = () => {
let date = new Date()
const hours = date.getHours()
if(hours < 12){
setTimeDay("Good Morning, ")
}else if (hours >= 12 && hours < 17){
setTimeDay("Good Afternoon, ")
}else{
setTimeDay("Good Evening, ")
}
}
useEffect(() => {
getName()
greeting()
setConnectionsChange(false)
}, [connectionsChange, timeDay])
if(name === "Lead School Counselor" ){
return(
<div>
<ReportingLayout auth={auth} allConnections={ allConnections } />
</div>
)
}else{
let defaultSchool
switch(name) {
case 'Jim Smith':
defaultSchool= "Cool School"
break;
case "Bob Williams":
defaultSchool= "Another School"
break;
}
return(
<Fragment>
<div className="container">
<div className='btn-group '>
<LogoutBtn setAuth = {setAuth}/>
</div>
<h1 className="d-flex mt-3 pl-3" > {timeDay}
{name} </h1>
<InputConnection defaultSchool={defaultSchool}
setConnectionsChange={setConnectionsChange}/>
<ListConnections allConnections={ allConnections }
setConnectionsChange={setConnectionsChange}/>
</div>
</Fragment>
)
}
}
导出默认仪表板;
下一个组件:
import React, { Fragment, useState } from "react";
import { toast } from 'react-toastify'
const InputTodo = ({ defaultSchool, setConnectionsChange }) => {
const today = new Date()
var formattedDate = today.toISOString().substr(0,10);
const [contact_type, setContactType] = useState("");
const [contact_method, setContactMethod] = useState("");
const [provision, setProvision] = useState("");
const [connection_date, setDate] = useState(formattedDate);
const [student_id, setStudentID] = useState("");
const [purpose, setPurpose] = useState("");
const [gender, setGender] = useState("");
const [yearGroup, setYearGroup] = useState("");
const [referral_discharge, setReferralDischarge] = useState("");
const [cp_referral, setCPReferral] = useState("");
const [school, setSchool] = useState(defaultSchool);
const onSubmitForm = async e => {
e.preventDefault();
try {
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("token", localStorage.token);
const body = {
contact_type,
contact_method,
provision,
connection_date,
student_id,
purpose,
gender,
yearGroup,
school,
referral_discharge,
cp_referral
};
const response = await fetch("/dashboard/connections", {
method: "POST",
headers: myHeaders,
body: JSON.stringify(body)
});
const parseResponse = await response.json();
console.count(parseResponse);
setConnectionsChange(true);
setContactType("")
setContactMethod("")
setProvision("")
setDate(formattedDate)
setStudentID("")
setPurpose("")
setGender("")
setYearGroup("")
setSchool(defaultSchool)
setReferralDischarge("")
setCPReferral("")
toast.success('Contact has been added', {
position: "top-center",
autoClose: 3000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
});
} catch (error) {
console.error(error.message);
}
};
return (
<Fragment>
<h1 className="text-center my-5 input-title">Communication Log</h1>
<form className="mt-5" onSubmit={onSubmitForm}>
{/* DATE */}
<input type="date" name="connection_date" placeholder="Date of Contact"
className="form-control" value={connection_date} onChange={e =>
setDate(e.target.value)}/>
{/* SCHOOL */}
<select type="text" name="school" placeholder="School" className="form-
control mt-3" defaultValue={defaultSchool} value={defaultSchool}
onChange={e => setSchool(e.target.value)}>
<option value="NADA" disabled>Choose your school</option>
<optgroup label= "SEN">
<option value="Cool School">Cool SChool</option>
<option value= "Another School">Another School</option>
</optgroup>
</select>
{/* SCHOOL ID */}
<input type="text" name="student_id" placeholder="Student ID"
className="form-control mt-3" value={student_id} onChange={e =>
setStudentID(e.target.value)}/>
{/* YEAR / GROUP */}
<select type="text" name="yeargroup" placeholder="year/group"
className="form-control mt-3" value={yearGroup} onChange={e =>
setYearGroup(e.target.value)}>
<option value="DEFAULT">Choose the Year/ Group</option>
<option value="yr01">yr01</option>
<option value="yr02">yr02</option>
<option value="yr03">yr03</option>
<option value="yr04">yr04</option>
<option value="yr05">yr05</option>
<option value="yr06">yr06</option>
<option value="yr07">yr07</option>
<option value="yr08">yr08</option>
<option value="yr09">yr09</option>
<option value="yr10">yr10</option>
<option value="yr11">yr11</option>
<option value="yr12">yr12</option>
</select>
{/* GENDER */}
<select type="text" name="gender" placeholder="gender" className="form-control mt-3" value={gender} onChange={e => setGender(e.target.value)}>
<option value="DEFAULT">Gender</option>
<option value="M">M</option>
<option value="F">F</option>
</select>
{/* REFERRAL OR DISCHARGE */}
<select type="text" name="referral_discharge" placeholder="referral_discharge" className="form-control mt-3" value={referral_discharge} onChange={e => setReferralDischarge(e.target.value)}>
<option value="DEFAULT">Was this a referral, continuation or discharge?</option>
<option value="referral">Referral</option>
<option value="discharge">Discharge</option>
<option value="continuation">Continuation</option>
</select>
{/* CONTACT TYPE */}
<select type="text" name="contact_type" placeholder="contact_type" className="form-control mt-3" value={contact_type} onChange={e => setContactType(e.target.value)}>
<option value="DEFAULT">Type of Contact</option>
<option value="student">student</option>
<option value="parent">parent</option>
<option value="emergeny contact">emergeny contact</option>
<option value="staff">staff</option>
<option value="social worker">social worker</option>
<option value="support staff">support staff</option>
<option value="SENCO">SENCO</option>
<option value="other">other</option>
</select>
{/* CONTACT METHOD */}
<select type="text" name="contact_method" placeholder="contact_method" className="form-control mt-3" value={contact_method} onChange={e => setContactMethod(e.target.value)}>
<option value ="DEFAULT">Contact Mode/ Method</option>
<option value="in-person">in-person</option>
<option value="text">text</option>
<option value="whatsapp">whatsapp</option>
<option value="phone call">phone call</option>
<option value="email">email</option>
<option value="check-in">check-in</option>
<option value="classroom presentation">classroom presentation</option>
<option value="session">session</option>
<option value="video chat">video chat</option>
<option value="group">group session</option>
<option value="crisis intervention">crisis intervention</option>
<option value="home visit">home visit</option>
<option value="sbst, mdt, case conference">sbst, mdt, case conference</option>
<option value="outside agency meeting">outside agency meeting</option>
<option value="other meeting">other meeting</option>
</select>
{/* CP_REFERRAL */}
<select type="text" name="cp_referral" placeholder="cp_referral" className="form-control mt-3" value={cp_referral} onChange={e => setCPReferral(e.target.value)}>
<option value="DEFAULT">Was this a CP Referral?</option>
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
{/* <div className='mt-3'>
<p>Is this a CP REFERRAL?</p>
<div className="form-check-inline">
<input className="form-check-input" type="radio" name="cp_referral" id="y" value={cp_referral} onClick={(e)=> setCp_referral(e.target.value)}/>
<label className="form-check-label">Yes</label>
</div>
<div className="form-check-inline">
<input className="form-check-input" type="radio" name="cp_referral" id="n" value={cp_referral} onClick={(e)=> setCp_referral(e.target.value)}/>
<label className="form-check-label">No</label>
</div>
</div> */}
{/* PURPOSE */}
<textarea className="form-control mt-3" name="purpose" placeholder="What was the purpose of the connection?" value={purpose} onChange={e => setPurpose(e.target.value)}></textarea>
{/* PROVISION */}
<textarea className="form-control mt-3" name="provision" placeholder="Provision/Support Agreed Upon/ Plan Forward (When Necessary) / Any Additional Notes" value={provision} onChange={e => setProvision(e.target.value)}></textarea>
{/* BUTTON */}
<button className="btn btn-success btn-block mt-3 mb-5">Add</button>
</form>
</Fragment>
); };
导出默认 InputTodo;
【问题讨论】:
-
请分享一个完整的代码示例。
-
您似乎在询问至少几个问题,请将 SO 问题限制为单个特定问题,并提供足够的代码供其他人理解并查看问题所在。更多的代码总比不够好,但太多的代码和不够一样糟糕。我怀疑你的
useEffect正在调用greeting()导致渲染循环。greeting更新了效果的依赖数组中列出的timeDay,但不清楚原因,因为它没有在效果中使用。 -
没有主要问题是为什么它需要两次点击才能正常运行;就是这样。
-
name在初始渲染之后 是否总是“Jim Smith”或“Bob Williams”之一?defaultSchool在初始渲染中未定义。InputConnection和InputTodo之间还有什么,或者它们实际上是同一个组件?你能澄清一下你所说的学校被提交与否是什么意思吗?您是否只是再次单击“添加”,没有与表单字段交互,并且表单按预期工作?您能否创建一个 running 代码框来重现此问题?
标签: reactjs forms react-hooks async.js