【问题标题】:How To Export State From Another module of reactjs如何从 reactjs 的另一个模块导出状态
【发布时间】:2020-05-09 22:57:18
【问题描述】:

我们开始以 3 名刚开始反应的学生的身份开展一个项目。我想拆分代码,这样每个人都可以同时处理一些事情。但是当我尝试在 App.js 中使用 icon-bar.js 的状态时,我收到了错误消息。 应用.js

import React, {Component} from 'react';
import './App.css';
import IconBar from './components/icon-bar';
import Events from './components/events';

function App() {
  return (
    <div className="App">
      <h1 className="Title">ENAKS</h1>
      <IconBar />
      <Events />
  <div className="mainModeFrame"><p1>{this.state.mode}</p1></div>
    </div>
  );
}

export default App;

icon-bar.js

import React, {Component} from 'react';
import '../App.css';

class IconBar extends Component {
    constructor() {
        super()
        this.state = {
            mode: 'Hi'
        }
    }
    render() {
        return(
                <div className="icon-bar">
                <div className="iconHolder">
                <img src="/images/2dlogo.png" alt="" className="icons" onClick={() => this.setState({mode: '2d'})}/>
                <img src="/images/3dlogo.png" alt="" className="icons" onClick={() => this.setState({mode: '3d'})}/>
                <img src="/images/flag.png" alt="" className="icons" onClick={() => this.setState({mode: 'edit'})}/>
                <img src="/images/tracker.png" alt="" className="icons" onClick={() => this.setState({mode: 'track'})}/>
        <div>{this.state.mode}</div>
                </div>
         </div>
              )
    }
}


export default IconBar;

如何使用我的“模式”状态来更改 App.js 中的 p1

【问题讨论】:

  • 查看 redux。
  • @CiBoz 我正在起草我的答案。答案如下。
  • 将模式置于父 comp 状态并在渲染 &lt;IconBar mood={this.state.mood} /&gt; 中作为 prop 传递,并使用 this.props.mood 在子 comp 中访问

标签: javascript reactjs


【解决方案1】:

找到正确的组件来保存您的状态很重要。在这里,您想将您的模式移动到父组件状态并从子组件作为道具访问它。

我看到您的子组件正在设置模式,这有点棘手,因为它现在将保持在父状态,那么该怎么做呢?

在父渲染中调用组件时,您在父渲染中创建回调并将该回调设置为道具。

然后,您需要在每个图像元素上设置 onClick 事件处理程序,以在您的子组件中调用事件处理程序(在本例中为 handleClick)。

然后,此事件处理程序将获取目标元素的 id,并使用 this.props.onUpdateMode(我们作为 prop 传递的回调)将其传递给父元素。

父回调从子回调接收数据,并相应地更新状态。

参考:Lifting State Up

import React, {Component} from 'react';
import './App.css';
import IconBar from './components/icon-bar';
import Events from './components/events';

class App() extends Component {
  constructor(props) {
        super(props)
        this.state = {
            mode: null
        }
        this.updateMode = this.updateMode.bind(this);
    }

  updateMode = (newMode) => {

      this.setState({mode: newMode});
  }


  return (
    <div className="App">
      <h1 className="Title">ENAKS</h1>
      <IconBar onUpdateMode={this.updateMode}  mode={this.state.mode} />
      <Events />
  <div className="mainModeFrame"><p1>{this.state.mode}</p1></div>
    </div>
  );
}

export default App;

import React, {Component} from 'react';
import '../App.css';

class IconBar extends Component {
    constructor(props) {
        super(props)

        this.handleClick=this.handleClick.bind(this);
    }

    handleClick(e) {

      let mode = e.target.id;
      this.props.onUpdateMode(mode);

    }


    render() {
        return(
                <div className="icon-bar">
                <div className="iconHolder">
                <img src="/images/2dlogo.png" id="2d" alt="" className="icons" onClick={this.handleClick} />
                <img src="/images/3dlogo.png" id="3d" alt="" className="icons" onClick={this.handleClick}/>
                <img src="/images/flag.png" id="edit" alt="" className="icons" onClick={this.handleClick}/>
                <img src="/images/tracker.png" id="track" alt="" className="icons" onClick={this.handleClick}/>
        <div>{this.props.mode}</div>
                </div>
         </div>
              )
    }
}


export default IconBar;

【讨论】:

  • 谢谢。这完美无缺。就一件事。我无法让 this.props.mode 正确渲染。即使它编译时没有错误,IconBar 中的 div 也会返回空。我的问题可能在哪里。 (我稍微更新了代码。)
  • 如果你在handleClick方法中使用console.log(e.target.id),控制台中是否显示了正确的模式?
【解决方案2】:

有两种方法可以做到这一点。

第一个是使用redux之类的东西。您可以在其中拥有可以在不同组件之间共享的状态的全局存储。

第二个是在父组件中发出状态。这里的图标栏应该是父组件app.js 的子组件。从父组件中,您将函数作为道具传递,并且该函数应该接受一个可以是状态的参数

下面的图标栏现在接受道具(见构造函数和超级)

import React, {Component} from 'react';
import '../App.css';

class IconBar extends Component {
    constructor(props) { // 
        super(props)
        this.state = {
            mode: 'Hi'
        }
    }
    render() {
        return(
                <div className="icon-bar">
                <div className="iconHolder">
                <img src="/images/2dlogo.png" alt="" className="icons" onClick={() => this.setState({mode: '2d'})}/>
                <img src="/images/3dlogo.png" alt="" className="icons" onClick={() => this.setState({mode: '3d'})}/>
                <img src="/images/flag.png" alt="" className="icons" onClick={() => this.setState({mode: 'edit'})}/>
                <img src="/images/tracker.png" alt="" className="icons" onClick={() => this.setState({mode: 'track'})}/>
        <div>{this.state.mode}</div>
                </div>
         </div>
              )
    }
}


export default IconBar;

然后在 app.js 中

import React, {Component} from 'react';
import './App.css';
import IconBar from './components/icon-bar';
import Events from './components/events';

function App() {
   const getStateFromChild = state => {
  // body of function 
  // return something 
  }

  return (
    <div className="App">
      <h1 className="Title">ENAKS</h1>
      <IconBar  upsideEmit={getStateFromChild} />
      <Events />
  <div className="mainModeFrame"><p1>{this.state.mode}</p1></div>
    </div>
  );
}

export default App;

您希望何时将状态发送到父组件取决于您。

[更新:] 我在我的open source repo 中做了一些非常相似的事情。而不是浏览整个代码,look at this line

这里有一个父组件,其中有子组件Checkboxes

<CheckBoxes 
  options={options}
  upsideEmit={onChangeHandler}
  defaultColor={defaultColor}
  />

CheckBoxes 传递一个函数 onChangeHandler upsideEmit={onChangeHandler}(忽略函数体)

const onChangeHandler =  (data, errorMessage=null) => {
    // Error Message is usually passed from the child components (look ad date componenet example )
    if (!errorMessage && (data === '' || data)) { // Doing data = "" in case someone want to remove last char of a string
      const currentData = {...payload}
      currentData[key] = data
      setPayloadData(currentData)
    } else if (errorMessage) {
      setErrorData({status: true, message: errorMessage})
    }
    return
  }

现在,如果您在复选框组件中查看此 line,我正在将我的子状态传递给父组件

  const toggleState = (index) => {
    let copyState = [...state]
    const previousState = copyState[index]['value']
    if (multipleSelect) {
      // Setting all other values as false, since the array for checkbox won't in normal scenario be big, we can just itterate and set it to false
      copyState = copyState.map(element => {
        element.value = false
        return element
      })
    } 
    copyState[index]['value'] = !previousState 
    setState(copyState)
    upsideEmit(copyState)
}

如果这有帮助,请给 repo 一个星号。

【讨论】:

  • 嗯,这是一个很好的答案。我认为第二种选择,在父组件中发出状态听起来像是一个好的开始。如果应用程序增长并且状态管理变得一团糟。看看 redux。
  • 为了获得 this.state.mode,我需要向 getStateFromChild 写入什么特别的东西。我无法让它工作。 (这是我第一次完整的反应项目对不起。)
  • 另一个答案解决了我的问题,但代码看起来更干净。我会在几个小时后尝试。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-25
  • 2017-05-12
  • 1970-01-01
  • 1970-01-01
  • 2021-11-07
  • 1970-01-01
相关资源
最近更新 更多