【发布时间】:2021-03-30 21:27:55
【问题描述】:
更新:
这是一个codesandbox 示例!
我有一个 textarea 组件,我在其中逐行执行验证:
UI 中的错误消息是一组对象,这些对象具有基于文本所在行的 id 属性和将容纳错误的 message 属性。 e.g. {id: 1, message: 'error message', name: 'text from line'}
据我了解,您不能在循环中设置状态,因为不能保证结果。a
这是获取字符串的 setMessage 函数:
setMessage 在我的验证函数中被调用:
function setMessage(data) {
console.log('data', data);
console.log("arrFromVariableTypeNameString ", arrFromVariableTypeNameString);
let allMessages = [...messagesContainer];
function drop(data, func) {
var result = [];
for (var i = 0; i < data.length; i++) {
var check = func(data[i]);
console.log("check ", check);
if (check) {
console.log("i + 1 ", i + 1);
result = data.slice(i, i + 1);
break;
}
}
return result;
}
for (var i = 0; i < arrFromVariableTypeNameString.length; i++) {
var match = drop(allMessages, e => e.id === i + 1);
if (match?.length) {
match[0] = {
...match[0],
...{
message: data,
name: arrFromVariableTypeNameString[i]
}
}
console.log("match ", match);
console.log("allMessages ", allMessages);
allMessages = allMessages.map(t1 => ({
...t1,
...match.find(t2 => {
console.log("t2.id === t1.id ", t2.id === t1.id);
return t2.id === t1.id
})
}))
} else {
allMessages.push({
name: arrFromVariableTypeNameString[i],
id: i + 1,
message: data
})
}
}
setMessagesContainer(allMessages)
}
这是整个组件:
export function VariableSetupModal({
exisitingVariableTypes
}) {
const dispatch = useDispatch();
const [isOpen, setIsOpen] = useState();
const [variableTypeName, setVariableTypeName] = useState('');
const [clipboardData, setClipboardData] = useState('')
const [pasted, setIsPasted] = useState(false)
const [messages, setMessages] = useState('');
const [messagesContainer, setMessagesContainer] = useState([]);
var arrFromVariableTypeNameString = variableTypeName.split('\n');
useEffect(() => {
function setMessage(data) {
console.log('data', data);
console.log("arrFromVariableTypeNameString ", arrFromVariableTypeNameString);
let allMessages = [...messagesContainer];
function drop(data, func) {
var result = [];
for (var i = 0; i < data.length; i++) {
var check = func(data[i]);
console.log("check ", check);
if (check) {
console.log("i + 1 ", i + 1);
result = data.slice(i, i + 1);
break;
}
}
return result;
}
for (var i = 0; i < arrFromVariableTypeNameString.length; i++) {
var match = drop(allMessages, e => e.id === i + 1);
if (match ? .length) {
match[0] = { ...match[0],
...{
message: data,
name: arrFromVariableTypeNameString[i]
}
}
console.log("match ", match);
console.log("allMessages ", allMessages);
allMessages = allMessages.map(t1 => ({ ...t1,
...match.find(t2 => {
console.log("t2.id === t1.id ", t2.id === t1.id);
return t2.id === t1.id
})
}))
} else {
allMessages.push({
name: arrFromVariableTypeNameString[i],
id: i + 1,
message: data
})
}
}
setMessagesContainer(allMessages)
}
function validator(variableType) {
var data = {
variableType: variableType,
}
var rules = {
variableType: "regex:^[a-zA-Z0-9_ ]+$|min:3|max:20",
}
var messages = {
min: `Enter at least three characters.`,
max: `Don't exceed more than twenty characters.`,
regex: `No special characters (but spaces) allowed.`
}
validate(data, rules, messages)
.then(success => {
console.log('Variable Type Entered correctly.', success)
setMessage('');
return
})
.catch(error => {
console.log('error', error)
setMessage(error[0].message);
return
});
}
function checkIfArrayIsUnique(myArray) {
if (myArray.length === 50) setMessages('Only 50 Variable Types allowed.');
return myArray.length === new Set(myArray).size;
}
arrFromVariableTypeNameString.map((variableType, i, thisArr) => {
function findDuplicates(uniqueCount) {
var count = {},
result = '';
uniqueCount.forEach((i) => {
count[i] = (count[i] || 0) + 1;
});
console.log(count);
return Object.keys(count).map((k) => {
if (count[k] > 1) return result.concat(`Variable Type ${k}: appears ${count[k]} times.`)
}).filter((item) => item !== undefined)
}
if (checkIfArrayIsUnique(thisArr)) {
if (validator(variableType)) {
return thisArr;
}
} else {
setMessage(findDuplicates(thisArr).map(s => < > {
s
} < br / > < />));
return;
}
})
return () => {
setMessagesContainer([])
console.log("messagesContainer clean up ", messagesContainer);
}
}, [variableTypeName])
const handlePaster = (e) => {
e.persist()
setIsPasted(true);
setClipboardData(e.clipboardData.getData('text'));
}
const handleChange = (e) => {
e.persist()
var {
keyCode
} = e;
var {
value
} = e.target;
if (keyCode === 13) {
setVariableTypeName(`${value}\n`);
return;
} else if ((pasted == true) && (keyCode == 13)) {
setVariableTypeName(`${variableTypeName.concat(clipboardData)}\n`);
setIsPasted(false);
return;
} else if ((pasted == true) && (keyCode !== 13)) {
setVariableTypeName(`${variableTypeName.concat(clipboardData)}`);
setIsPasted(false);
return;
} else {
setVariableTypeName(`${value}`);
return;
}
}
return ( <
div >
<
Button className = "button"
onClick = {
evt => setIsOpen(true)
} > Add Variable Types < /Button> <
div style = {
{
display: "none"
}
} >
<
Modal id = "myModal"
heading = "Variable Type Configuration"
description = ""
userClosable = {
true
}
autoFocus = {
false
}
actionsLeft = { <
React.Fragment >
<
Button display = "text"
onClick = {
handleCancel
} > Cancel < /Button> <
Button display = "primary"
onClick = {
handleSave
} > Save < /Button> <
/React.Fragment>
}
isOpen = {
isOpen
}
onRequestClose = {
detail => {
handleCancel(false);
setMessagesContainer([])
}
} >
{
exisitngVarFormatted != "" && < Textbox
as = "textarea"
type = "text"
value = {
exisitngVarFormatted
}
disabled >
Existing <
/Textbox>}
<
Textbox
as = "textarea"
type = "text"
placeholder = "Variable Types"
maxLength = "100"
value = {
variableTypeName
}
onPaste = {
e => handlePaster(e)
}
onChange = {
e => handleChange(e)
} >
To Create <
/Textbox>
{
messagesContainer.map((messageObj, i, arr) => {
console.log("messageObj ", messageObj);
return messageObj.message != '' ? ( <
p key = {
messageObj.id
}
className = "Messages" > {
`Error on line ${i + 1}: ${messageObj.message}`
} < /p>
) : null
})
}
<
/Modal> <
/div> <
/div >
);
}
这就是让我把剩下的头发拔掉的原因。
在日志中,您可以清楚地看到对象设置正确,但在 UI 中,消息不是唯一的! 70号线
任何帮助将不胜感激!
【问题讨论】:
-
将鼠标悬停在蓝色背景的
i上,然后阅读工具提示的内容。如果对象支持序列化,请考虑使用console.log(JSON.stringify(variable, null, 2))。 -
哇,谢谢!我从来没有对此感到陌生!任何想法如何解决它?
-
我不确定是什么问题;数据应该是什么,它是什么等等。最好有一个minimal reproducible example。请注意,我现在在代码中没有看到
setState或钩子的使用,所以可能是我遗漏了一些东西。 -
我不需要个人解释。我问这些问题是为了让您edit您的问题并在问题中进行解释,以便更多人理解并提供帮助。我不一定会回答这个问题——我有工作要做:)。
-
@HereticMonkey 感谢您建议我做一个minimal reproducible example 不知道为什么我没有想到这一点。你认为我应该重新问这个问题吗?
标签: javascript reactjs for-loop react-hooks setstate