1 一个组件的所有实例都引用第一个实例而不是它本身; 2 儿童道具只有在两次调用父母的 setState 后才会更新

如何解决1 一个组件的所有实例都引用第一个实例而不是它本身; 2 儿童道具只有在两次调用父母的 setState 后才会更新

更新:我通过为所有“评级”组件提供唯一名称轻松解决了第一个问题,但关于 2 x setState 修复道具的问题仍然存在。

其实我有两个问题。第二个来自试图解决第一个。 最初的问题是每个 SongScoring 组件的每个 onChange Rating 属性中的“this”指向 SongScoring 类的第一个实例而不是它自身:

父代码:

import React,{ Component } from 'react';
import './Assess.css';
import { Accordion } from 'react-bootstrap';
import SongScoring from './SongScoring';

class Assess extends Component {
  constructor(props) {
    super(props);

    const songs = [
      {
        track: "song1",},{
        track: "song2",{
        track: "song3",{
        track: "song4",]

    this.state = {
      songs: songs,};
  }

  render() {
    return (
      <div className="root">
        <Accordion defaultActiveKey="0">
          {
            this.state.songs.map((song,index) => (
              <SongScoring song={song} key={index.toString()} index={index} />
            ))
          }
        </Accordion>
      </div>
    );
  }
}

export default Assess;

子代码:

import React,{ Component } from 'react';
import './SongScoring.css';
import { Accordion,Card,Container,Row } from 'react-bootstrap';
import ReactPlayer from "react-player";
import Rating from '@material-ui/lab/Rating';
import Box from '@material-ui/core/Box';

const labels = {
  0.5: 'Unpleasant',1: 'Bearable',1.5: 'Bearable+',2: 'Intriguing',2.5: 'Intriguing+',3: 'Ok',3.5: 'Ok+',4: 'Pleasant',4.5: 'Pleasant+',5: 'Excellent',};

class SongScoring extends Component {

  constructor(props) {
    super(props);
    this.state = {
      song: props.song,key: props.index.toString(),score: props.song.score || 0,hover: props.song.score || -1,onChange: this.props.onChange,onChangeActive: this.props.onChangeActive
    }
  }

  render() {
    return (
      <>
        <Card>
          <Accordion.Toggle as={Card.Header} variant="link" eventKey={this.state.key}>
            {this.state.key}
            <Rating name="read-only" value={this.state.score} precision={0.5} readOnly />
          </Accordion.Toggle>
          <Accordion.Collapse eventKey={this.state.key}>
            <Card.Body style={{ display: 'flex',alignItems: 'center',lineHeight: '1' }}>
              <Container>
                <Row className='scoring-row'>
                  <ReactPlayer
                    url="https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3"
                    width="400px"
                    height="50px"
                    playing={false}
                    controls={true}
                    style={{ outline: 'none' }}
                  />
                </Row>
                <Row className='scoring-row'>
                  <Rating
                    name="song-rating"
                    value={this.state.score}
                    precision={0.5}
                    onChange={(event,newScore) => {
                      this.setState({
                        score: newScore
                      });
                    }}
                    onChangeActive={(event,newHover) => {
                      this.setState({
                        hover: newHover
                      });
                    }}
                    style={{ marginTop: '40px' }}
                  />
                </Row>
                <Row className='scoring-row'>
                  {this.state.score !== 0 && <Box>{labels[this.state.hover !== -1 ? this.state.hover : this.state.score]}</Box>}
                </Row>
              </Container>
            </Card.Body>
          </Accordion.Collapse>
        </Card>
      </>
    );
  }
}

export default SongScoring;

经过多次尝试通过更改箭头函数和绑定、将 onChange 和 onChangeActive 放入状态等来解决此问题后,我最终决定尝试通过将 onChange 和 onChangeActive 函数从父级传递到孩子。

这就是我想出的(onChange 和 onChangeActive 中有 console.log 而不是 setState,但我们真正关心的是“this”引用):

父代码:

import React,]

    this.songScoring = [];
    const onChange = [];
    const onChangeActive = [];
    for (let i = 0; i < songs.length; i++) {
      this.songScoring.push(React.createRef());
      onChange.push(function (event,newScore) {
        console.log("onChange: ",this);
      });
      onChangeActive.push(function (event,newHover) {
        console.log("onChangeActive: ",this);
      });
    }

    this.state = {
      songs: songs,onChange: onChange,onChangeActive: onChangeActive
    };

  }

  componentDidMount() {
    console.log(this.state.songScoring);
    const onChange = [];
    const onChangeActive = [];
    for (let i = 0; i < this.state.songs.length; i++) {
      onChange.push(this.state.onChange[i].bind(this.songScoring[i],1));
      onChangeActive.push(this.state.onChangeActive[i].bind(this.songScoring[i]));
    }    
    this.setState({
      onChange: onChange,onChangeActive: onChangeActive
    });//,() => this.setState({unicorn: 1}));
  }

  render() {
    return (
      <div className="root">
        <Accordion defaultActiveKey="0">
          {
            this.state.songs.map((song,index) => (
              <SongScoring song={song} ref={this.songScoring[index]} key={index.toString()} index={index} onChange={this.state.onChange[index]} onChangeActive={this.state.onChangeActive[index]} />
            ))
          }
        </Accordion>
      </div>
    );
  }
}

export default Assess;

子代码:

import React,};

class SongScoring extends Component {

  constructor(props) {
    super(props);
    this.state = {
        song: props.song,onChangeActive: this.props.onChangeActive
    }
    
  }

  componentDidUpdate(prevProps,prevState){
    if (prevProps.onChange !== this.state.onChange){
        this.setState({
            onChange: prevProps.onChange,onChangeActive: prevProps.onChangeActive
        })
    }

  }

  render() {
    return (
        <>
          <Card> 
            <Accordion.Toggle as={Card.Header} variant="link" eventKey={this.state.key}>
              {this.state.key}
              <Rating name="read-only" value={this.state.score} precision={0.5} readOnly />
            </Accordion.Toggle>
            <Accordion.Collapse eventKey={this.state.key}>
              <Card.Body style={{ display: 'flex',lineHeight: '1' }}>
                <Container>
                  <Row className='scoring-row'>
                    <ReactPlayer
                      url="https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3"
                      width="400px"
                      height="50px"
                      playing={false}
                      controls={true}
                      style={{outline: 'none'}}
                    />
                  </Row>
                  <Row className='scoring-row'>
                    <Rating
                      name="song-rating"
                      value={this.state.score}
                      precision={0.5}
                      onChange={this.state.onChange}
                      onChangeActive={this.state.onChangeActive}
                      style={{ marginTop: '40px' }}
                    />
                  </Row>
                  <Row className='scoring-row'>
                    {this.state.score !== 0 && <Box>{labels[this.state.hover !== -1 ? this.state.hover : this.state.score]}</Box>}
                  </Row>
                </Container>
              </Card.Body>
            </Accordion.Collapse>
          </Card>
        </>
      );
  }
}

export default SongScoring;

在这个设置中,console.log in onChange 和 onChangeActive 都输出'undefined'。

现在,如果我取消对片段的注释:'//,() => this.setState({unicorn: 1}));' (独角兽是一个虚拟的、未使用的变量)在 onChange 和 onChangeActive 的父级、console.log 中很好地打印出“this”作为各自 SongScoring 组件的引用。

因此我的问题是:

  • 这两个问题发生了什么?是“评级”组件的错误吗?
  • 如何比对未注释的片段使用第二种方法更有效地解决我最初的问题?

更新:我通过为所有“评级”组件提供唯一名称轻松解决了第一个问题,但关于 2 x setState 修复道具的问题仍然存在。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res