【问题标题】:Attempting to lift React state while maintaining access to a variable calculated lower down尝试提升 React 状态,同时保持对较低计算变量的访问
【发布时间】:2021-10-28 22:06:19
【问题描述】:

我正在学习 React,并试图准确了解应该将多少状态提升到更高的水平。我的理解是,一般来说,只有在具有共同祖先的多个组件需要时才应该提升一个状态。

就我而言,我正在尝试构建一个对被点击做出反应的日历。日历本身应该对被点击做出物理反应,但侧边栏应该显示所选日期的其他信息。目前,整体结构如下:

App
  Calendar
    Header
    Square
  Sidebar
    LoginInterface

我想要的行为使我相信应用程序应该拥有handleClick(squareNum) 方法的所有权,因为它可以将其作为道具传递给 Squares,但 handleClick 方法将能够影响在侧边栏。当我试图提升我的状态时,我的问题就出现了,而我基本上没有带走整个 Calendar 实现。

显然,仅提升 handleClick(squareNum) 是有问题的,因为 squareNum 未在该级别定义。当我在日历中渲染我的 Squares 时,我将 handleClick 函数作为道具传递给他们,以及 squareNum(字面意思是在循环期间创建 Square 的编号)。为了将 handleClick 提升到 App 中,我还需要提升 Squares 本身的创建。我认为我可以这样做,然后将<div>{row}</div>作为{props.children}传递给Calendar,但我觉得我当时真的在折磨程序的逻辑,而不是坚持只提升的心态编写其他组件所需的代码。

React 文档在https://reactjs.org/docs/handling-events.html#passing-arguments-to-event-handlers 中提到了与我的问题类似的问题,但我认为这里的网格并不完美。虽然我确实想将参数传递给事件处理程序,但我想在中间级组件中执行此操作,我想在 Calendar 中传递 Square 的 id,但我想在 App 中传递 handleClick 本身。

这似乎不是一个不常见的用例,所以我觉得我一定错过了一些 React 的基本内容。谁能建议我如何将中级参数实现到传递的函数道具中,或者类似的东西?

class Calendar extends React.Component{
  constructor(props){
    super(props)
    this.setState({
      squares: Array(42).fill(null),
    })
  }

  handeClick(i){
    let squares = this.state.squares.slice()
    squares[i] = 'clicked!'
    this.setState({squares: squares})
  }

  renderSquare(squareNum){
    return(
     <Square
        //other props
        onClick={props.handleClick(squareNum)}
      />
  }

  render(){
    let squareNum = 0;
    let cal = [];

    return(
      for(let i=0;i<5;i++){
        let row = [];
        for (let j=0;j<7;j++){
          row.push(this.renderSquare(squareNum));
          squareNum++;
        }
        cal.push(<div //key //className>{row}</div>);
      }
    );
  }
}

function Square(props){
    //irrelevant for this example
}

class App extends React.Component{
  constructor(props){
    super(props)
    this.setState=({
      renderedDate: //combined with the squareNum, this allows calculation of which day was clicked
    })

  /**HandleClick would ideally be here so that the sidebar can have the selected date passed down to it as a prop**/

  render(){
    <div>
      <Calendar //renderedDate />
      <Sidebar //props />
    </div>
  }
}

【问题讨论】:

    标签: javascript reactjs state


    【解决方案1】:

    对于您正在尝试做的事情 - 在层次结构中的其他位置的一个组件和另一个组件之间共享信息 - 将状态提升到作为两者的祖先的组件是正确的做法。但这并不意味着 处理函数 也需要在顶层定义 - 任何合理大小的应用程序都会很快变得混乱且难以管理。

    您需要在顶层拥有(并向下传递)状态和状态设置器。将状态向下传递到侧边栏,状态和状态设置器通过日历向下传递到方块。然后,在各个方格内定义点击处理程序,并在需要时调用状态设置器。

    // App:
      render(){
        <div>
          <Calendar renderedDate={this.state.renderedDate} />
          <Sidebar setRenderedDate={d => this.setState({ renderedDate: d }) />
        </div>
      }
    

    然后传递 setRenderedDate 直到到达Square,并让 Square 在其点击处理程序中调用该函数(一个道具)。

    【讨论】:

    • 我强烈建议您也添加一个反应上下文方法来执行此操作..因为这是上下文的一个很好的用例:)
    • 是的,如果树真的很深,那么避免到处传递道具是一个不错的选择。问题中的代码看起来不够复杂,不需要它,但随着应用程序的进一步发展,它可能会。
    猜你喜欢
    • 2020-12-20
    • 1970-01-01
    • 2018-03-17
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-08
    相关资源
    最近更新 更多