我有一个<select>
标记,我用它来创建自己的自定义<SelectField>
组件,如下所示:
export default function SelectField(props) {
/*
PARAMS:
- fieldname (String)
- fieldID (String)
- options (Array([Object, Object...]) [{"option_value": "option_name"}, ...])
- init_value (String "option_value")
*/
const generate_options = () => {
// Function for handling SelectField options
let element_list = [];
element_list.push(
<SelectOption key={0} option_value="" option_text="None" />
);
var count = 1;
if (!Array.isArray(props.options)) {
for (var [value, name] of Object.entries(props.options)) {
element_list.push(
<SelectOption key={count} option_value={value} option_text={name} />
);
count += 1;
}
} else {
props.options.forEach((subject) => {
element_list.push(subject.to_option());
});
}
return element_list;
};
const nameToString = () => {
// Converts props.fieldname into a properly formatted name
if(props.fieldname.indexOf("_")){
var full_field_name = `${props.fieldname.split("_").join(" ")}`;
return `${full_field_name[0].toUpperCase() + full_field_name.slice(1)}`;
};
return `${props.fieldname[0].toUpperCase() + props.fieldname.slice(1)}`;
};
return (
<div className="form-group">
<label htmlFor={props.fieldname}>
{nameToString()}:
</label>
<select
name={`${props.fieldname}`}
id={`${props.fieldID}`}
className="countries"
defaultValue={props?.init_value ? `${props.init_value}` : ""}
>
{generate_options()}
</select>
</div>
);
}
(PS。不要介意className -它真的不应该相关。但谁知道像我这样的初学者。DS)。现在,我想使用该字段在我的web应用程序(由Django提供支持)中为Subjects
创建一个<select>
标记,并为其创建了一个如下所示的子组件:
export function SubjectSelectField(props) {
const [subjects, setSubjects] = useState([]);
useEffect(() => {
const getSubjects = async () => {
let reqObj = new RequestHandler("/courses/subjects/");
const data = await reqObj.sendRequest();
setSubjects(
data.map((item) => {
return new Subject(item);
})
);
};
getSubjects();
}, []);
console.log({ subjects });
return <SelectField options={subjects} {...props} />;
}
在使用此组件呈现页面时,我得到了以下console.logs:
{
"subjects": [
{
"id": 6,
"name": "Art"
},
{
"id": 4,
"name": "Biology"
},
{
"id": 5,
"name": "Chemistry"
},
{
"id": 3,
"name": "Geography"
},
{
"id": 2,
"name": "Language"
},
{
"id": 1,
"name": "Mathmatics"
},
{
"id": 7,
"name": "Physics"
},
{
"id": 8,
"name": "Social Studies"
}
]
}
作为参考,这是我的自定义Subject
类(ES6):
export class Subject {
constructor({ id, name }) {
this.id = id;
this.name = name;
}
to_option() {
return (
<SelectOption
key={this.id}
option_value={this.id}
option_text={this.name}
/>
);
};
}
和<SelectOption>
组件:
export function SelectOption(props) {
return <option value={`${props.option_value}`} >{`${props.option_text}`}</option>;
}
因此,我期望的输出是<SelectField>
自动将selected
属性赋给具有<SelectField>
的init_value
属性值的选项。我将<SelectField>
用于另一种类型的字段,我称之为<CountrySelectField>
,它工作得很好。我希望预先选择的国家是根据它的init_value
正确选择的。
该组件如下所示:
export function CountrySelectField(props) {
return (
<SelectField
init_value={props?.student?.country ? `${props.student.country}` : ""}
{...props}
/>
);
}
正如我所提到的,如果我将一个值传递给这个组件的init_value
属性,它就会像预期的那样执行,并使用设置了selected
属性的正确选项进行呈现。
<SubjectSelectField>
没有按照我期望的方式呈现--正确的<option>
设置了selected
属性。
为什么它不起作用?
编辑:
将Subject类更改为React功能组件:
export function Subject(props){
const id = props.subject.id;
const name = props.subject.name;
console.log(id, name, props.subject);
if(props.option){
return(
<SelectOption
key={id}
option_value={id}
option_text={name}
/>
);
}
return(
<h1>{name} - {id}</h1>
);
}
为了让其他东西正常工作,我也改变了这些东西:
export function SubjectSelectField(props) {
// ...
setSubjects(
data.map((item) => {
return <Subject subject={item} />;
})
);
// ...
该选项仍不会被自动选择。我还有其他的字段,它们使用的大部分都是相同的逻辑(SelectField在其他地方也用得很好),但是我在这里显然搞乱了一些东西。
PS。如果你有时间进行语言监督,你肯定也有时间研究这个问题。“不是吗,”halfer?天啊..。DS.
发布于 2021-11-09 18:08:34
我松了一口气,因为我自己解决了这个问题,问题是我从来没有在SubjectSelecField
上实现检查,以便仅在从服务器加载Subject
时才呈现<select>
字段。例如:
export function SubjectSelectField(props) {
const [subjects, setSubjects] = useState([]);
// Here I use 'loaded' as a check variable when rendering.
const [loaded, setLoaded] = useState(false);
useEffect(() => {
const getSubjects = async () => {
let reqObj = new RequestHandler("/courses/subjects/");
try{
const data = await reqObj.sendRequest();
setSubjects(
data.map((item) => {
return <Subject subject={item} />;
})
);
// If the Subjects load properly, set 'loaded' to true.
setLoaded(true);
}
catch(error){
console.log(`Something went wrong when trying load Subjects from server!`);
console.error(error);
// Else we make sure its set to false.
setLoaded(false);
}
};
getSubjects();
}, []);
console.log({ subjects });
// Here, before rendering, we check for the 'loaded' variable
// to make sure the <select> tag doesn't try to load without
// the <option> tags. Otherwise, the 'defaultValue' prop won't work.
if(loaded) return <SelectField init_value={props.init_value} options={subjects} {...props} />;
return <span>Loading Subject list...</span>;
}
至少感谢大家对它的研究:)
https://stackoverflow.com/questions/69835505
复制相似问题