- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
因此,这是一个用户可以添加部分来添加问题(以构建测验)的表单,我注意到当我填写答案选择
并将文件放入我的 >dropZone
(drop 可以工作,但无法正确更新,您可以忽略这一点)Answer Choices
和 dropZone
重新渲染,并且刷新等字段会变为空。
我不完全确定为什么会发生这种情况,我尝试过查看类似的问题,但无法让它发挥作用。 Here is my CodeSandbox with my App.
我认为这可能是我的 Questions
组件中的 addQuestion
函数。这是代码:
addQuestion = question => {
questionIdx++;
var newQuestion = { uniqueId: uuid(), question: "" }
this.setState(prevState => ({
questions: [...prevState.questions, newQuestion]
}));
return { questions: newQuestion }
};
我是 React 和 Js 的新手,所以任何提示/解释都会有很多帮助。谢谢!
最佳答案
当您添加新问题并更新 Questions
组件状态变量 questions
(数组类型)时,整个组件(Questions
和它的子级)经历一个更新过程,根据新状态重新计算输出 DOM 树(虚拟 DOM),并将其与状态更改前的虚拟 DOM 进行比较。在“重新渲染”任何内容之前,它会检查两个版本的虚拟 DOM 是否不同,如果不同,它将尽可能高效地重新渲染发生更改的部分。
在您的情况下,重新计算会在许多 Question
中看到许多 Answers
组件,并且由于 Answers
没有任何 Prop ,因此基本上是对其初始状态的全新渲染,其中包括 4 个空输入。我能想到的最简单的解决方案是在 Questions
组件的状态下,确保 this.state.questions
数组中的每个对象都有一个 answers
属性(对象数组类型)。在 addQuestion
方法中修改 var newQuestion = { uniqueId: uuid(), Question: ""};
以在与该问题相关的答案中包含此数据。
然后,在渲染每个单独的问题时,将此答案数据(答案数组)作为 Prop 传递给 Answers
,然后根据索引依次传递给每个单独的 Answer
组件(一个对象或一个字符串)。同时,您必须将 updateAnswers
方法作为 prop 传递给 Question
,然后再传递给 Answers
和 Answer
,当Answer
的输入字段更改时调用。问题 id 和答案 id 需要传递给此方法,以最终修改现在应存储在 Questions
组件状态中的答案数据。我调整了下面沙箱中的代码以按照这些思路工作,尽管我没有确保清除所有损坏:
import React, { Component } from "react";
import "./App.css";
var uuid = require("uuid-v4");
// Generate a new UUID
var myUUID = uuid();
// Validate a UUID as proper V4 format
uuid.isUUID(myUUID); // true
class DropZone extends Component {
constructor(props) {
super(props);
this.state = {
file: "",
fileId: uuid(),
className: "dropZone"
};
this.handleChange = this.handleChange.bind(this);
this._onDragEnter = this._onDragEnter.bind(this);
this._onDragLeave = this._onDragLeave.bind(this);
this._onDragOver = this._onDragOver.bind(this);
this._onDrop = this._onDrop.bind(this);
}
handleChange(file = "") {
this.setState({
file: URL.createObjectURL(file)
});
//document.getElementsByClassName("dropZone").style.backgroundImage = 'url(' + this.state.file + ')';
}
componentDidMount() {
window.addEventListener("mouseup", this._onDragLeave);
window.addEventListener("dragenter", this._onDragEnter);
window.addEventListener("dragover", this._onDragOver);
document
.getElementById("dragbox")
.addEventListener("dragleave", this._onDragLeave);
window.addEventListener("drop", this._onDrop);
}
componentWillUnmount() {
window.removeEventListener("mouseup", this._onDragLeave);
window.removeEventListener("dragenter", this._onDragEnter);
window.addEventListener("dragover", this._onDragOver);
document
.getElementById("dragbox")
.removeEventListener("dragleave", this._onDragLeave);
window.removeEventListener("drop", this._onDrop);
}
_onDragEnter(e) {
e.stopPropagation();
e.preventDefault();
return false;
}
_onDragOver(e) {
e.preventDefault();
e.stopPropagation();
return false;
}
_onDragLeave(e) {
e.stopPropagation();
e.preventDefault();
return false;
}
_onDrop(e, event) {
e.preventDefault();
this.handleChange(e.dataTransfer.files[0]);
let files = e.dataTransfer.files;
console.log("Files dropped: ", files);
// Upload files
console.log(this.state.file);
return false;
}
render() {
const uniqueId = this.state.fileId;
return (
<div>
<input
type="file"
id={uniqueId}
name={uniqueId}
class="inputFile"
onChange={e => this.handleChange(e.target.files[0])}
/>
<label htmlFor={uniqueId} value={this.state.file}>
{this.props.children}
<div className="dropZone" id="dragbox" onChange={this.handleChange}>
Drop or Choose File
<img src={this.state.file} id="pic" name="file" accept="image/*" />
</div>
</label>
<div />
</div>
);
}
}
class Answers extends Component {
constructor(props) {
super(props);
this.state = {
answers: props.answers,
};
this.handleUpdate = this.handleUpdate.bind(this);
}
// let event = {
// index: 1,
// value: 'hello'
// };
handleUpdate(event) {
//if ("1" == 1) // true
//if ("1" === 1) //false
// var answers = this.state.answers;
// answers[event.index] = event.value;
// this.setState(() => ({
// answers: answers
// }));
var answers = this.state.answers.slice();
for (var i = 0; i < answers.length; i++) {
if (answers[i].answerId == event.answerId) {
answers[i].answer = event.value;
break;
}
}
this.setState(() => ({
answers: answers
}));
this.props.updateAnswers(answers)
console.log(event);
}
render() {
return (
<div id="answers">
Answer Choices<br />
{this.state.answers.map((value, index) => (
<Answer
key={`${value}-${index}`}
onUpdate={this.handleUpdate}
value={value}
number={index}
name="answer"
/>
))}
</div>
);
}
}
class Answer extends Component {
constructor(props) {
super(props);
this.state = {
answer: props.value.answer,
answerId: props.value.answerId,
isCorrect: props.value.isCorrect,
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
this.setState({
answer: value
});
this.props.onUpdate({
answerId: this.state.answerId,
value
});
// let sample = {
// kyle: "toast",
// cam: "pine"
// };
// sample.kyle
// sample.cam
}
render() {
return (
<div>
<input type="checkbox" />
<input
type="text"
value={this.state.answer}
onChange={this.handleChange}
key={this.state.answerId}
name="answer"
/>
{/*console.log(this.state.answerId)*/}
</div>
);
}
}
var questionIdx = 0;
class Questions extends Component {
constructor(props) {
super(props);
this.state = {
questions: []
};
this.handleUpdate = this.handleUpdate.bind(this);
this.handleUpdate = this.handleUpdate.bind(this);
this.removeQuestion = this.removeQuestion.bind(this);
}
handleUpdate(event) {
//if ("1" == 1) // true
//if ("1" === 1) //false
var questions = this.state.questions.slice();
for (var i = 0; i < questions.length; i++) {
if (questions[i].uniqueId == event.uniqueId) {
questions[i].question = event.value;
break;
}
}
this.setState(() => ({
questions: questions
}));
console.log(event, questions);
}
updateAnswers(answers, uniqueId) {
const questions = this.state.questions
questions.forEach((question) => {
if (question.uniqueId === uniqueId) {
question.answers = answers
}
})
this.setState({
questions,
})
}
addQuestion = question => {
questionIdx++;
var newQuestion = {
uniqueId: uuid(),
question: "",
answers: [
{ answer: "", answerId: uuid(), isCorrect: false,},
{ answer: "", answerId: uuid(), isCorrect: false,},
{ answer: "", answerId: uuid(), isCorrect: false,},
{ answer: "", answerId: uuid(), isCorrect: false,}]
}
this.setState(prevState => ({
questions: [...prevState.questions, newQuestion]
}));
return { questions: newQuestion };
};
removeQuestion(uniqueId, questions) {
this.setState(({ questions }) => {
var questionRemoved = this.state.questions.filter(
props => props.uniqueId !== uniqueId
);
return { questions: questionRemoved };
});
console.log(
"remove button",
uniqueId,
JSON.stringify(this.state.questions, null, " ")
);
}
render() {
return (
<div id="questions">
<ol id="quesitonsList">
{this.state.questions.map((value, index) => (
<li key={value.uniqueId}>
{
<RemoveQuestionButton
onClick={this.removeQuestion}
value={value.uniqueId}
/>
}
{
<Question
onUpdate={this.handleUpdate}
value={value}
number={index}
updateAnswers={(answers) => this.updateAnswers(answers, value.uniqueId) }
/>
}
{<br />}
</li>
))}
</ol>
<AddQuestionButton onClick={this.addQuestion} />
</div>
);
}
}
class Question extends Component {
constructor(props) {
super(props);
this.state = {
question: props.value.question,
uniqueId: props.value.uniqueId,
answers: props.value.answers,
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
this.setState({
question: value
});
this.props.onUpdate({
uniqueId: this.state.uniqueId,
value
});
}
render() {
return (
<div id={"questionDiv" + questionIdx} key={myUUID + questionIdx + 1}>
Question<br />
<input
type="text"
value={this.state.question}
onChange={this.handleChange}
key={this.state.uniqueId}
name="question"
/>
<DropZone />
<Answers updateAnswers={this.props.updateAnswers} answers={this.state.answers} />
</div>
);
}
}
class IntroFields extends Component {
constructor(props) {
super(props);
this.state = {
title: "",
author: ""
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
console.log([name]);
this.setState((previousState, props) => ({
[name]: value
}));
}
render() {
return (
<div id="IntroFields">
Title:{" "}
<input
type="text"
value={this.state.title}
onChange={this.handleChange}
name="title"
/>
Author:{" "}
<input
type="text"
value={this.state.author}
onChange={this.handleChange}
name="author"
/>
</div>
);
}
}
class AddQuestionButton extends Component {
addQuestion = () => {
this.props.onClick();
};
render() {
return (
<div id="addQuestionButtonDiv">
<button id="button" onClick={this.addQuestion} />
<label id="addQuestionButton" onClick={this.addQuestion}>
Add Question
</label>
</div>
);
}
}
class RemoveQuestionButton extends Component {
removeQuestion = () => {
this.props.onClick(this.props.value);
};
render() {
return (
<div id="removeQuestionButtonDiv">
<button id="button" onClick={this.removeQuestion} key={uuid()} />
<label
id="removeQuestionButton"
onClick={this.removeQuestion}
key={uuid()}
>
Remove Question
</label>
</div>
);
}
}
class BuilderForm extends Component {
render() {
return (
<div id="formDiv">
<IntroFields />
<Questions />
</div>
);
}
}
export default BuilderForm;
关于javascript - 不需要的 React 组件重新渲染?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51565583/
我错过了什么,我已完成 的安装指南中要求的所有步骤 native 脚本 运行 tns doctor 给我以下输出... C:\abc\xyz>tns doctor √ Getting environm
尝试从 {addToCart(book)}}/>}> 传递数据至}> 问题: 购物车 ( render={()=> ) 收到 null,但没有收到我尝试发送的对象 已放置“console.log...
这是 _app.tsx 的外观: function MyApp({ Component, pageProps }: AppProps) { return } 我在构建项目时遇到了这个错误: Ty
我的 Laravel Vue 组件收到以下警告: [Vue warn]: Avoid mutating a prop directly since the value will be overwrit
根据这个example更详细this one我刚刚遇到了一件奇怪的事情...... 如果我使用方法作为 addTab(title,icon,component) 并且下一步想使用 setTabComp
目前我有一个捕获登录数据的表单,一个带有 TIWDBGrid 的表单,它应该返回与我从我的 mysql 数据库登录时创建的 user_id 关联的任何主机,以及一个共享数据模块。 下面是我的登录页面代
在我的react-native应用程序中,我目前有一个本地Android View (用java编写)正确渲染。当我尝试将我的react-native javascript 组件之一放入其中时,出现以
我为作业编写了简单的代码。我引用了文档和几个 youtube 视频教程系列。我的 react 代码是正确的我在运行代码时没有收到任何错误。但是这些 react-boostrap 元素没有渲染。此代码仅
几周前我刚刚开始使用 Flow,从一周前开始我就遇到了 Flow 错误,我不知道如何修复。 代码如下: // @flow import React, { Component } from "react
我想在同一个 View 中加载不同的 web2py 组件,但不是同时加载。我有 5 个 .load 文件,它们具有用于不同场景的表单字段,这些文件由 onchange 选择脚本动态调用。 web2py
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 6年前关闭。 Improve t
Blazor 有 InputNumber将输入限制为数字的组件。然而,这呈现了一个 firefox 不尊重(它允许任何文本)。 所以我尝试创建一个过滤输入的自定义组件: @inherits Inpu
我在学习 AngularDART 组件时编写了以下简单代码,但没有显示任何内容,任何人都可以帮助我知道我犯了什么错误: 我的 html 主文件:
我想在初始安装组件时或之后为 div 设置动画(淡入)。动画完成后,div 不应消失。我正在尝试使用 CSSTransition 组件并查看 reactcommunity.org 上的示例,但我根本无
我需要一个 JSF 组件来表示甘特图。是否有任何组件库(如 RichFaces)包含这样的组件? 最佳答案 JFreeChart有甘特图和PrimeFaces有一个图像组件,允许您动态地流式传输内容。
从软件工程的角度来看,组件、模块和子系统之间有什么区别? 提前致谢! 最佳答案 以下是 UML 2.5 的一些发现: 组件:该子句指定一组结构,可用于定义任意大小和复杂性的软件系统。特别是,它将组件指
我有使用非托管程序集(名为 unmanaged.dll)的托管应用程序(名为 managed.exe)。到目前为止,我们已经创建了 Interop.unmanaged.dll,managed.exe
我有一个跨多个应用程序复制的 DAL(我知道它的设计很糟糕,但现在忽略它),我想做的是这个...... 创建一个将通过所有桌面应用程序访问的 WCF DAL 组件。任何人都可以分享他们对关注的想法吗?
我有一个 ComboBox 的集合声明如下。 val cmbAll = for (i /** action here **/ } 所有这些都放在一个 TabbedPane 中。我想这不是问题。那么我
使用 VB6 创建一个 VB 应用程序。应用程序的一部分显示内部的闪存。 当我使用 printform它只是打印整个应用程序。我不知道如何单独打印闪光部分。任何帮助,将不胜感激!.. 谢谢。 最佳答案
我是一名优秀的程序员,十分优秀!