You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

在Styled Components中通过React Props数组条件修改样式的问题

问题解析:React Styled Components中基于Props数组条件设置样式失败

问题场景回顾

你正在开发一个钢琴键盘React组件,通过传入notes字符串数组来标记需要高亮的琴键,以此避免为每种状态创建冗余图片。但在尝试在styled component中根据数组元素是否存在修改背景色时,页面抛出了TypeError: Cannot read property 'contains' of undefined的错误,尝试indexOf、转字符串用includes也都遇到同样问题。

错误原因分析

出现这个错误主要有两个核心原因:

  1. 数组方法误用:JavaScript数组并没有contains方法,正确判断元素是否存在的方法是includes()(ES6+支持)或者indexOf() !== -1
  2. 空值未处理:当props.notes未被传入、或者传入的值为undefined时,直接调用数组方法会触发"读取undefined属性"的错误。比如如果父组件调用<Keyboard/>时没传notesprops.notes就是undefined,此时调用undefined.includes()必然报错。

解决方案

1. 修复数组方法+添加空值保护

首先修改你的styled component代码,替换错误的containsincludes,同时用**可选链操作符?.**或者条件判断来处理notes可能为undefined的情况:

import styled, { css } from 'styled-components';

// 假设你的基础样式定义如下
const WhiteKey = css`
  /* 白键基础样式 */
  width: 40px;
  height: 160px;
  border: 1px solid #ccc;
`;
const PerfectKey = css`
  background-color: #ffd700; /* 高亮颜色示例 */
`;
const UnselectedWhiteKey = css`
  background-color: #fff;
`;

// 修复后的C1组件
const C1 = styled.div`
  ${WhiteKey}
  ${props => props.notes?.includes('cp') ? PerfectKey : UnselectedWhiteKey}
`;

可选链?.的作用是:如果props.notes存在(不为undefinednull),则继续调用includes;否则直接返回undefined,此时三元表达式会走默认的UnselectedWhiteKey分支。

如果你的环境不支持可选链,也可以用条件判断兜底:

${props => (props.notes && props.notes.includes('cp')) ? PerfectKey : UnselectedWhiteKey}

2. 给Keyboard组件设置默认Props

为了从源头避免notesundefined,可以给Keyboard组件设置默认props,确保notes始终是一个数组:

const Keyboard = (props) => {
  // ...组件内容
};

Keyboard.defaultProps = {
  notes: []
};

3. 优化:通用Key组件减少冗余代码

你当前为每个琴键都创建了单独的styled component(C1、D1、E1等),这会产生大量重复代码。更优的方式是创建一个通用的Key组件,接收note标识和isBlack属性,统一处理样式:

const BlackKey = css`
  /* 黑键基础样式 */
  width: 28px;
  height: 100px;
  background-color: #333;
  margin: 0 -14px;
  z-index: 1;
`;
const UnselectedBlackKey = css`
  background-color: #333;
`;

const Key = styled.div`
  ${props => props.isBlack ? BlackKey : WhiteKey}
  ${props => props.notes.includes(props.note) ? PerfectKey : (props.isBlack ? UnselectedBlackKey : UnselectedWhiteKey)}
`;

// 在Keyboard组件中使用:
const Keyboard = (props) => {
  return (
    <Container>
      <KeyboardBox>
        <WhiteKeys>
          <Key note="cp" isBlack={false} {...props} />
          <Key note="dma" isBlack={false} {...props} />
          <Key note="ema" isBlack={false} {...props} />
          <Key note="fp" isBlack={false} {...props} />
          <Key note="gp" isBlack={false} {...props} />
          <Key note="ama" isBlack={false} {...props} />
          <Key note="bma" isBlack={false} {...props} />
        </WhiteKeys>
        <BlackKeys>
          <Key note="db1" isBlack={true} {...props} />
          <Key note="eb1" isBlack={true} {...props} />
          <Key note="gb1" isBlack={true} {...props} />
          <Key note="ab1" isBlack={true} {...props} />
          <Key note="bb1" isBlack={true} {...props} />
        </BlackKeys>
      </KeyboardBox>
    </Container>
  )
};

Keyboard.defaultProps = {
  notes: []
};

这种方式不仅减少了重复代码,还让后续新增琴键或修改样式逻辑变得更高效。

内容的提问来源于stack exchange,提问作者rchrdnsh

火山引擎 最新活动