【问题标题】:Child Components are not being re-rendered子组件没有被重新渲染
【发布时间】:2018-05-19 20:12:33
【问题描述】:

我是 React 新手。作为学习练习,我正在构建一个国际象棋应用程序

我想根据父级的状态更改子级的 DOM。目前,父组件的状态发生变化时,子组件没有变化。

父组件

class Game extends Component{
    constructor(){
        super();
        this.state = {
            game :{ 
                board_position = { 'One' : ''}
            }
        }

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

    handleClick(){
        let p = this.state.game.board_position;

        // some computations on p
        p = { board_position : { 'One' : Math.random() } }

        this.setState({
            game : p
        })

        //this.forceUpdate(); // Just trying different methods to make it work
    }

    render(){
        return(
            <div onClick={(e) => this.handleClick(e) }>
                <Piece {...this.state.game.board_position} />
            </div>
        )
    }
}

子组件

Class Piece extends Component{

    constructor(){
        super(props);
        this.state = {
            clr : ''
        }
    }

    componentWillMount(){
        let c;

        // some computations that change value of c based on props
        if( typeof ( this.props.game.one) == number ){
            c = 'Red'
        } else {
            c = 'Blue'
        }


        this.setState({
            clr : c
        })

    }

    render(){
        return(
            <span>{this.state.clr}</span>
        )
    }
}

在调用手柄点击方法时,游戏状态发生了变化。但是,看不到 Child 的后续变化。

谁能帮帮我?我哪里错了?

我不确定如何按照over here 的建议实现 ref。但是,我认为这不是一个好的解决方案。可能我在概念上有一些误解。

PS:请忽略任何语法错误。此代码是真实代码的精简版。 如果您想查看完整代码 - go over here

【问题讨论】:

  • 这里发生了很多奇怪的事情。你不应该强制更新。设置状态应该为您处理。此外,永远不要直接改变状态。您拼错了constructor,并且this.state.clr 周围没有大括号。您没有使用从父级传递的道具,并且 componentWillMount 运行一次......因此在第一次渲染后不会发生任何变化
  • 嗨,正如我所说,请忽略语法错误。这是代码的精简版本,而不是真正的代码本身。我还给出了真实代码的链接
  • 提供minimal reproducible example 是您的工作。没有人会为您梳理您的代码。自己找出问题并提供一个没有语法错误的完整示例。
  • 你没有使用父组件传递的props
  • 我正在使用 prop 进行一些计算。变量 C 的值将取决于 props 的值。但不直接使用道具

标签: javascript reactjs react-native components


【解决方案1】:

Piece 组件中的componentWillMount 只会触发一次。

您是否也在每次道具更改时更新您的状态?例如使用componentWillReceiveProps

您也可以直接在渲染函数中显示道具

render(){
    return(
        <span>{use the props directly here}</span>
    )
}

尽可能避免使用状态,并坚持仅基于 props 渲染组件。

【讨论】:

  • 感谢您的回复。我不能直接使用道具,因为我需要进行一些计算并使用计算出的值
  • 每次道具变化时都需要进行计算,不是吗?无论如何,不​​要在你的组件中进行计算,在高阶组件或状态管理系统中进行计算,而只使用你的 React 组件来显示数据。 React 是视图引擎而不是计算引擎。
  • 我明白了。但是这些计算将决定要在输出中呈现什么
  • 在你的渲染方法中进行计算,不要在Piece的状态下保存任何东西
【解决方案2】:

这是一个非常基本的反应过程:

class Game extends Component{
    constructor(){
        super();
        this.state = {
            game :{ 
                 board_position = { 'One' : ''}
             }
        }

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

    handleClick(e){
        let p = this.state.game.board_position;

        // some computations on p
        p = { board_position : { 'One' : Math.random() } }

        this.setState({
            game : p
        })
    }

    render(){
        return(
        <div onClick={this.handleClick}>
            <Piece board_position={this.state.game.board_position} />
        </div>
        )
    }
}

Child: //可以是一个函数而不是一个类

const Piece = ({board_position}) =>{
  const {board_position} = this.props;
  let clt = board_position;
  //do some stuff

  return(
    <span>{board_position}</span>
  );
};

如果你想做更多的计算,你可以使用 componentWillReceiveProps(newProps)

【讨论】:

    【解决方案3】:

    组件在 propsstates 发生变化时重新渲染。会根据 propsown states 的值调用某些生命周期方法。

    您访问 **props 的方式是错误的。** 应该是

    this.props.One
    

    你应该使用的生命周期方法是 componentWillReciveProps(nextProps)。在这种情况下,您应该像下面这样访问相关的道具

    nextProps.One
    

    我已经创建了一个有效的fiddle(如果你修复了这些代码有错误并查看了你的日志,你可以很容易地找出错误在哪里)

    【讨论】:

    • componentWillMount 只会被调用一次,所以游戏道具改变时游戏不会改变。
    • 对不起。构造函数被调用一次。每次组件要更新时都会调用 componentWillMount。但是是的,我使用了错误的生命周期方法。它应该是 componentWillReceiveProps。我现在已经更新了我的答案。
    猜你喜欢
    • 2020-01-22
    • 2017-06-11
    • 2021-11-24
    • 1970-01-01
    • 2018-08-12
    • 2019-06-01
    • 1970-01-01
    • 2020-02-13
    • 2021-11-18
    相关资源
    最近更新 更多