我想要 2 个功能性 React 组件:
一个
Data
组件,保存状态值,通过 props 传递:
a
SummedValue
也在状态中保存一个值,但将该值计算为其子级值的总和,其中其子级可以是 Data
或其他 SummedValue
组件,任意嵌套
我想像这样使用它们:
<SummedValue>
<Data value={3}/>
<Data value={5}/>
<SummedValue>
<Data value={4}/>
<Data value={1}/>
</SummedValue>
目前,在
SummedValue
组件中,我可以通过Data
单独从children.props.value
组件获取数据。但是我不知道如何从嵌套的 SummedValue
组件中获取这个值,因为它不是一个 prop。
基本上我认为这与将数据从子级传递到父级有关,但我找不到有效的配置
function SummedValue({children}) {
// how can I access this computed value in parent component?
let computedValue = 0;
// Only works for props, not internal values
children.forEach(child => {
if (child.props.value) {
value += child.props.value
}
})
return(
<div>
<span>SUMMED NUMBER IS: {computedValue}
{children}
</div>
)
}
您需要递归计算
Data
和 SummedValue
分量的总和。
Data
组件通过 props 保持其状态的值。
SummedValue
组件需要迭代其子组件并直接计算Data
组件的总和并递归处理嵌套的SummedValue
组件。
SummedValueContext
是为了将求和值传递到树上。
useContext(SummedValueContext)
用于获取父级的求和值更新器函数。
SummedValueContext.Provider
用于为其子级提供本地求和值更新器功能。
以下是上述功能的基本代码:
import React, { createContext, useContext, useState, useEffect } from 'react';
const SummedValueContext = createContext();
function Data({ value }) {
return <div>{value}</div>;
}
function SummedValue({ children }) {
const parentSummedValue = useContext(SummedValueContext);
const [computedValue, setComputedValue] = useState(0);
useEffect(() => {
let sum = 0;
const sumValues = (children) => {
children.forEach(child => {
if (child.props.value !== undefined) {
sum += child.props.value;
} else if (child.type === SummedValue) {
sum += child.props.children.reduce((acc, child) => {
if (child.props.value !== undefined) {
return acc + child.props.value;
} else if (child.type === SummedValue) {
return acc + sumValues(child.props.children);
}
return acc;
}, 0);
}
});
};
sumValues(children);
setComputedValue(sum);
if (parentSummedValue) {
parentSummedValue(sum);
}
}, [children, parentSummedValue]);
return (
<SummedValueContext.Provider value={setComputedValue}>
<div>
<span>SUMMED NUMBER IS: {computedValue}</span>
{children}
</div>
</SummedValueContext.Provider>
);
}
function App() {
return (
<SummedValue>
<Data value={3} />
<Data value={5} />
<SummedValue>
<Data value={4} />
<Data value={1} />
</SummedValue>
</SummedValue>
);
}
export default App;