我试图更新
inferredFacts
状态,但在这个过程中它必须先更新facts
状态,然后获取facts
状态的更新值然后处理inferredFacts
,问题是inferredFacts
赢了无法获取 facts
的更新值
我尝试过使用 useEffect 和 useMemo,但它只是给了我无限循环,尽管我不确定我是否正确实现了它。
顺便说一句,我正在研究前向链接
export default function useFacts(answers: boolean[]) {
const [facts, setFacts] = useState<Set<string>>(new Set([]));
const [inferredFacts, setInferredFacts] = useState<Set<string>>(new Set([]));
const addFact = useCallback((newFact: string) => {
setFacts((prevFacts) => new Set([...prevFacts, newFact]));
}, []);
function populateFacts() {
const tmpFacts = new Set<string>([]);
if (answers[0]) {
tmpFacts.add("a");
}
if (answers[1]) {
tmpFacts.add("b");
}
if (answers[2]) {
tmpFacts.add("c");
}
if (answers[3]) {
tmpFacts.add("f");
}
setFacts(tmpFacts);
}
const factsHasAll = useCallback(
// list = antecedent
(list: string[]) => {
const filteredFacts = list.filter((item) => facts.has(item));
if (filteredFacts.length === list.length) {
return true;
}
return false;
},
[facts]
);
const doForwardChaining = useCallback(
(rules: Rule[]) => {
const inferredFacts = new Set<string>([]);
while (true) {
let inferred = false;
for (const rule of rules) {
if (
factsHasAll(rule.antecedent) &&
!inferredFacts.has(rule.consequent)
) {
addFact(rule.consequent);
inferredFacts.add(rule.consequent);
inferred = true;
break;
}
}
if (!inferred) break;
}
setInferredFacts((prev) => new Set([...prev, ...inferredFacts]));
},
[addFact, factsHasAll]
);
return {
facts,
populateFacts,
doForwardChaining,
inferredFacts,
};
}
您正在更新状态,这是一个异步操作,然后同步检查状态是否发生变化。
相反,您必须获取当前状态,创建
tempFacts
Set
,同步更新和检查它,完成后更新状态。
const answersToFact = ['a', 'b', 'c', 'f'] as const;
// list = antecedent
const factsHasAll = (list: string[], facts: Set<string>) => list.every(item => facts.has(item));
export default function useFacts(answers: boolean[]) {
const [facts, setFacts] = useState<Set<string>>(new Set([]));
const [inferredFacts, setInferredFacts] = useState<Set<string>>(new Set([]));
function populateFacts() {
setFacts(answersToFacts.reduce((set, fact, idx) => {
if(answer[idx]).add(fact);
return set;
}, new Set<string>()));
}
const doForwardChaining = useCallback(
(rules: Rule[]) => {
const inferredFacts = new Set<string>([]);
const tempFacts = new Set(facts);
while (true) {
let inferred = false;
for (const rule of rules) {
if (
factsHasAll(rule.antecedent, tempFacts) &&
!inferredFacts.has(rule.consequent)
) {
tempFacts.add(rule.consequent);
inferredFacts.add(rule.consequent);
inferred = true;
break;
}
}
if (!inferred) break;
}
setFacts(facts);
setInferredFacts((prev) => new Set([...prev, ...inferredFacts]));
},
[facts]
);
return {
facts,
populateFacts,
doForwardChaining,
inferredFacts,
};
}