首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用UseReducer和UseContext进行调度后,状态变得不确定

使用UseReducer和UseContext进行调度后,状态变得不确定
EN

Stack Overflow用户
提问于 2022-04-22 17:57:10
回答 1查看 468关注 0票数 2

目标:我试图切换使用和上下文的3D模型的可见性。3D渲染是使用一个名为Xeokit的框架的React版本完成的。通过向Xeokit元素(XKTModel.js)提供支持,模型被呈现为画布元素(XKTModel.js)。

问题是,一旦发送了调度,状态就会变得没有定义。上下文只对给定给还原器的默认值起作用。哪个组件发送调度似乎并不重要。

我已经使用UseContext钩子将每个组件的状态写入控制台,以查看发生了什么。减速机也是一样。

我做了很多搜索,但找不到一个类似的问题正在解决。一个更有经验的人能发现我犯的错误吗?

背景创造:

代码语言:javascript
复制
import React from "react";

const ViewControlsContext = React.createContext()

export {ViewControlsContext as default}

减速机:

代码语言:javascript
复制
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}

应用程序:

代码语言:javascript
复制
import React from 'react';

import './App.scss'

import ThreeDeeCanvas from './Components/3DCanvas'

function App(){
  return (<div>
    <ThreeDeeCanvas />
  </div>)
};

export default App;

3 3DCanvas (将模型呈现到其中的组件提供上下文):

代码语言:javascript
复制
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模型的源和道具,使用上下文):

代码语言:javascript
复制
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控件的容器):

代码语言:javascript
复制
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视图道具的单独切换,发送调度):

代码语言:javascript
复制
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}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-22 20:45:29

您正在返回逗号运算符的结果,即console.log的结果,它是一个空返回。

逗号运算符

逗号运算符 (,)计算其每个操作数(从左到右),返回最后一个操作数的值。这允许您创建一个复合表达式,其中计算多个表达式,复合表达式的最终值是其成员表达式最右边的值。

解决方案

记录独立于还原器函数返回的状态和动作。

代码语言:javascript
复制
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;
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71972875

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档