我正在使用
React.js
,我一直在尝试在 useEffect()
钩子和 onClickHandler()
函数中使用其他函数,但是当我尝试获取一个对象的属性值时,我得到了 Undefined
作为参数传递给函数。
我第一次遇到这个问题是在开发这个
useEffect()
钩子的时候:
useEffect(() => {
const renderSegmentIfSetToTrue = (data) => {
if (data.segmentMetadata.selected === true) {
return arcGenerator({startAngle: data.segmentMetadata.startAngle, endAngle: data.segmentMetadata.endAngle});
}
return;
}
const circleSegmentsContainer = d3.select(circleSegmentsContainerRef.current);
circleSegmentsContainer
.selectAll('.circle-segment')
.data(musicKeysObject)
.join(
enter => enter.append('path')
.attr('d',data => renderSegmentIfSetToTrue(data))
.attr('class', 'circle-segment')
.attr('stroke', 'red'),
update => update.append('path')
.attr('d',data => renderSegmentIfSetToTrue(data))
.attr('class', 'circle-segment')
.attr('stroke', 'blue')
.attr('fill', 'green'),
exit => exit.append('path')
.attr('d',data => renderSegmentIfSetToTrue(data))
.attr('class', 'circle-segment')
.attr('stroke', 'blue')
.attr('fill', 'purple')
);
}, [musicKeysObject])
我也在使用 D3.js 尝试在这里做一些事情,但这与这个问题或问题无关。请注意
renderSegmentIfSetToTrue()
功能(是的,这是一个糟糕的名字,我稍后会更改它)。这个函数是在钩子的顶部定义的,你可以看到如果参数的某些属性为真(if (data.segmentMetadata.selected === true)
),那么我想返回一些东西,这部分又是无关的。
我最初在
useEffect()
钩子的外部定义了这个函数(它的定义就在上面),我会得到一个错误说明 Cannot read properties of Undefined (reading segmentMetadata)
。我通过移动要在钩子中定义的函数来解决这个问题,它工作正常。
我解释了所有这些,因为我现在遇到与
onClickHandler()
功能相关的类似问题。这是一个带有onClickHandler
功能的按钮(我也尝试过单独定义该功能并像onClick={myHandlerFunction}
一样调用它)
<button onClick={() => {
console.log('Button was clicked!')
setMusicKeysObject(musicKeysObject.map(({musicKey, index})=>
(index === 6) ? musicKey.segmentMetadata.selected = true : null
))}}>Click me!</button>
当我单击此按钮时,我得到了
Cannot read properties of null (reading 'segmentMetadata')
,但我也看到了与上面提到的相同的错误,其中指出properties of undefined
。这让我觉得我不理解与 React.js 钩子或普通 javascript 函数的“作用域”相关的东西。
为了进一步理解,这里是我定义的对象,它是在不同的模块中定义并导入的。然后我使用
useState()
钩子将导入的对象加载到 React.js 函数组件中的新本地对象中:
import musicKeys from '../../MusicKeys'
export default function CircleOfFifths() {
const [musicKeysObject, setMusicKeysObject] = useState(musicKeys);
// Other code below (including the useEffect() hook explained above and this component contains the button with the `onClickHandler` problem I am now facing).
// 1 example of a musicKey
var F_Major = {
segmentMetadata: {
startAngle: null,
endAngle: null,
selected: false
}
}
// An array of musicKeys
var musicKeys = [
C_Major,
G_Major,
D_Major,
A_Major,
E_Major,
B_Major,
F_sharp_Major,
C_sharp_Major,
A_flat_Major,
E_flat_Major,
B_flat_Major,
F_Major
]
// Generate segment metadata
// Adds the startAngle and endAngle of each segment to an array
// Uses cumulativeAngle to keep track of each segment
const sectorAngle = (Math.PI * 2) / 12;
var cumulativeAngle = 0;
for (let i = 0; i < musicKeys.length; i++) {
let startAngle = cumulativeAngle;
cumulativeAngle += sectorAngle;
let endAngle = cumulativeAngle;
musicKeys[i].segmentMetadata.startAngle = startAngle;
musicKeys[i].segmentMetadata.endAngle = endAngle;
}
export default musicKeys;
我觉得这与“作用域”有关,因为将函数放入
useEffect()
钩子之前解决了这个问题,但我想要一个可靠的/答案的解释来解释我在这里做错了什么,而不是理解。
我还认为使用 typescript 而不是 javascript 可能有助于解决这个问题,因为函数必须将特定类型传递给它,这样函数现在就会准确地知道它正在处理的对象,并且知道它可以获取某个属性的值。