目标:我试图切换使用和上下文的3D模型的可见性。3D渲染是使用一个名为Xeokit的框架的React版本完成的。通过向Xeokit元素(XKTModel.js)提供支持,模型被呈现为画布元素(XKTModel.js)。
问题是,一旦发送了调度,状态就会变得没有定义。上下文只对给定给还原器的默认值起作用。哪个组件发送调度似乎并不重要。
我已经使用UseContext钩子将每个组件的状态写入控制台,以查看发生了什么。减速机也是一样。
我做了很多搜索,但找不到一个类似的问题正在解决。一个更有经验的人能发现我犯的错误吗?
背景创造:
import React from "react";
const ViewControlsContext = React.createContext()
export {ViewControlsContext as default}减速机:
const ViewControlsReducer = (state, action) => {
switch (action.type) {
case 'POPULATE_STATE':
return action.state, console.log("populate dispatch: ", action, state)
case 'TOGGLE_SITE_VISIBILITY':
return {
...state,
//site_visibility: !state.site_visibility
//^commented out, as will cause an error because state undefined
}, console.log("toggle dispatch: ", action, state)
default:
return state, console.log("default: ", action, state)
}
}
export {ViewControlsReducer as default}应用程序:
import React from 'react';
import './App.scss'
import ThreeDeeCanvas from './Components/3DCanvas'
function App(){
return (<div>
<ThreeDeeCanvas />
</div>)
};
export default App;3 3DCanvas (将模型呈现到其中的组件提供上下文):
import React, { useEffect, useReducer } from 'react'
import { Container, Col, Row } from 'react-bootstrap'
import XKTModel from './XKTModel';
import ThreeDeeControls from './3DControls';
import LogoCanvas from './LogoCanvas'
import ViewControlsContext from '../Context/ViewControlsContext';
import ViewControlsReducer from '../Reducers/ViewControlsReducer';
const ThreeDeeCanvas = () => {
const def = {
site_visibility: false
}
const [viewControls, dispatch] = useReducer(ViewControlsReducer, def)
useEffect(() => {
dispatch({type: 'POPULATE_STATE', state: def})
dispatch({type: 'POPULATE_STATE', state: def}) //test, with this state is undefined
}, [])
console.log("3dcanvas: ", viewControls)
return (
<div>
<LogoCanvas/>
<Col className='ThreeDeeWindow'>
<ViewControlsContext.Provider value={{viewControls, dispatch}} >
<XKTModel/>
<ThreeDeeControls/>
</ViewControlsContext.Provider>
</Col>
</div>
)
}
export {ThreeDeeCanvas as default}XKTModel ( 3D模型的源和道具,使用上下文):
import React, { useContext } from 'react';
import { navCubeSettings } from '../models';
import { XKTViewer } from 'xeokit-react';
import ViewControlsContext from '../Context/ViewControlsContext';
import { IFCObjectDefaultColors } from '../default_colors';
const mainModel = {
id: 'main_model',
src: './xkt/Showcase.xkt',
metaModelSrc: './xkt/Showcase.json',
edges: true,
objectDefaults: IFCObjectDefaultColors,
}
const siteModel = {
id: 'site_model',
src: './xkt/ShowcaseSite.xkt',
metaModelSrc: './xkt/ShowcaseSite.json',
edges: true
}
const XKTModel = () => {
const {viewControls} = useContext(ViewControlsContext)
console.log("XKTModel: ", viewControls)
//siteModel.visible = viewControls.site_visibility
//^commented out, as will cause an error because state undefined
return (
<XKTViewer
canvasID="modelCanvas"
width={800}
height={800}
models={[mainModel, siteModel]}
navCubeSettings={navCubeSettings}
/>
)
};
export default XKTModel;3 3DControls (用于单个3D控件的容器):
import React, { useContext } from 'react'
import { Container, Col, Row } from 'react-bootstrap'
import ThreeDeeControl from './3DControl'
import ViewControlsContext from '../Context/ViewControlsContext'
const ThreeDeeControls = () => {
const {viewControls} = useContext(ViewControlsContext)
console.log("3dcontrols: ", viewControls)
return (
<Container className='ThreeDeeControls p-0 d-flex justify-content-between'>
<ThreeDeeControl id='site' label='Show site'/>
</Container>
)
}
export {ThreeDeeControls as default}3 3DControl (用于更改3D视图道具的单独切换,发送调度):
import React, { useState, useContext, useReducer } from 'react'
import { Container, Form } from 'react-bootstrap'
import ViewControlsContext from '../Context/ViewControlsContext'
const ThreeDeeControl = ({id, label}) => {
const {viewControls, dispatch} = useContext(ViewControlsContext)
console.log("3dsinglecontrol: ", viewControls)
const [isSwitchOn, setIsSwitchOn] = useState(false);
const onSwitchAction = () => {
setIsSwitchOn(!isSwitchOn);
dispatch({type: 'TOGGLE_SITE_VISIBILITY'})
}
return (
<Form className='ThreeDeeControl'>
<Form.Check
type="switch"
id={id}
label={label}
checked={isSwitchOn}
onChange={onSwitchAction}
/>
</Form>
)
}
export {ThreeDeeControl as default}发布于 2022-04-22 20:45:29
您正在返回逗号运算符的结果,即console.log的结果,它是一个空返回。
逗号运算符 (
,)计算其每个操作数(从左到右),返回最后一个操作数的值。这允许您创建一个复合表达式,其中计算多个表达式,复合表达式的最终值是其成员表达式最右边的值。
解决方案
记录独立于还原器函数返回的状态和动作。
const ViewControlsReducer = (state, action) => {
switch (action.type) {
case 'POPULATE_STATE':
console.log("populate dispatch: ", { action, state });
return action.state;
case 'TOGGLE_SITE_VISIBILITY':
console.log("toggle dispatch: ", { action, state });
return {
...state,
site_visibility: !state.site_visibility
};
default:
console.log("default: ", { action, state });
return state;
}
}https://stackoverflow.com/questions/71972875
复制相似问题