首页 > 解决方案 > React Hook 更新不改变子组件的样式

问题描述

我已经尝试解决这个问题几个星期,但无法理解出了什么问题。我想切换按钮的背景颜色。我的组件级别是 App --> LabAssign --> Test。我正在更新 App 中获取的数据:

setFetchedSamples(fetchedSamples.map(sample => sample.labid === id ? {...sample, status: newStatus, [field]: newTestStatus} : sample))

然后重新渲染组件 LabAssign:

import React from 'react'
import Test from 'Components/Buttons/Test'
import Icon from 'Components/Buttons/Icon'

const AssignLab = (props) => {

  let sample = props.sample
  let unassigned = '#d3d3d3d'
  let assigned = props.view === 'normal' ? '#ED4A56' : 'dodgerblue'
  let reviewed = 'black'
  let completed = 'gray'
  let started = 'yellow'

  let testDetails = [    
    {
      id: sample.labid,
      name: 'ac sa',
      field: 'statusacsa',
      status: sample.statusacsa,
      colorStatus: sample.statusacsa === 'reviewed' ? reviewed : sample.statusacsa === 'completed' ? completed : sample.statusacsa === 'started' ? started : sample.statusacsa === 'assigned' ? assigned : unassigned,
      colorNormal: sample.statusacsa === null || sample.statusacsa === '' ? unassigned : '#EDB84A' //orange
    },
    {
      id: sample.labid,
      name: 'av',
      field: 'statusav',
      status: sample.statusav,
      colorStatus: sample.statusav === 'reviewed' ? reviewed : sample.statusav === 'completed' ? completed : sample.statusav === 'started' ? started : sample.statusav === 'assigned' ? assigned : unassigned,
      colorNormal: sample.statusav === null || sample.statusav === '' ? unassigned : '#EDB84A' //orange
    }
  ]

  let i = 0
  let tests = testDetails.map((test) => {
    i++

    return(
      <Test key={i} test={test} view={props.view} isTodo={props.isTodo} onClick={props.onClick} />
    )
  })

  return (
    <span>
      {tests}      
    </span>
  )
}

export default AssignLab

然后最后测试重新渲染:

import React, {useState} from 'react'

const Test = (props) => {

  // const style = {
  //   backgroundColor: props.view === 'normal' ? props.test.colorNormal : props.test.colorStatus,
  //   border: '1px solid black',
  //   borderRadius: 5,
  //   color: props.view === 'status' && (props.test.status === 'completed ' || props.test.status === 'reviewed') ? 'white' : 'black',
  //   display: props.isTodo && props.test.status !== 'assigned' && props.test.status !== 'started' ? 'none' : 'inline-block',
  //   margin: 5
  // }

  let style = {
    backgroundColor: props.view === 'normal' ? props.test.colorNormal : props.test.colorStatus,
    border: '1px solid black',
    borderRadius: 5,
    color: props.view === 'status' && (props.test.status === 'completed ' || props.test.status === 'reviewed') ? 'white' : 'black',
    display: props.isTodo && props.test.status !== 'assigned' && props.test.status !== 'started' ? 'none' : 'inline-block',
    margin: 5
  }

  let style2 = {
    backgroundColor: props.view === 'normal' ? props.test.colorNormal : props.test.colorStatus,
    border: '2px solid red',
    borderRadius: 5,
    color: props.view === 'status' && (props.test.status === 'completed ' || props.test.status === 'reviewed') ? 'white' : 'black',
    display: props.isTodo && props.test.status !== 'assigned' && props.test.status !== 'started' ? 'none' : 'inline-block',
    margin: 5
  }


let test = <button type='button' onClick={props.onClick} style={style} data-id={props.test.id} data-field={props.test.field} data-status={props.test.status}>{props.test.name}</button>

  if (props.test.name === 'ac sa' && props.test.id === 20234) {
    console.log('test data: ' + JSON.stringify(props.test))
    console.log('view: ' + props.view)
    console.log('style: ' + JSON.stringify(style))
  }



  return (
    (props.test.name === 'ac sa' && props.test.id === 20234 && props.test.status === 'assigned') ?
    <button type='button' onClick={props.onClick} style={style} data-id={props.test.id} data-field={props.test.field} data-status={props.test.status}>{JSON.stringify(style)}</button> :
    (props.test.name === 'ac sa' && props.test.id === 20234 && props.test.status === '') ?
    <button type='button' onClick={props.onClick} style={style2} data-id={props.test.id} data-field={props.test.field} data-status={props.test.status}>{JSON.stringify(style)}</button> :
    <button type='button' onClick={props.onClick} style={style} data-id={props.test.id} data-field={props.test.field} data-status={props.test.status}>{props.test.name}</button>
  )
}

export default Test

我在 Test 组件中留下了我的 console.logs 和三元组,以展示我为解决这个问题所做的一些努力。最初,我在 Test 中使用了一个带有三元组的 let style={...} 来更改按钮的背景颜色,但即使我在 App 中更新了我的钩子状态,它也不会改变。我的 console.logs 显示样式已更新为正确的颜色,但按钮在渲染后未反映它。但是,如果我将样式对象放在按钮的显示值中......按钮的显示值会更新为颜色名称,而不是背景颜色。如果我在 Test 的返回中放置一个三元并在 style 和 style2 之间切换,颜色不会更新。最后,如果我放置

style = {{backgroundColor: 'purple'}}

代替

style={style}

在Test返回的三元内,它会改变颜色。有什么能解释一下为什么 React 没有在传递新道具时重新渲染 backgroundColor 吗?

此外,如果测试最初是“未分配”并且我单击它,它会将背景颜色从“灰色”更改为“红色”,但如果我再次单击它,它将不会更新。如果我单击一个已分配且背景颜色为“红色”或其他颜色的测试,它不会改变。

标签: reactjsreact-hooks

解决方案


推荐阅读