更新功能组件道具不会改变样式

Posted

技术标签:

【中文标题】更新功能组件道具不会改变样式【英文标题】:Updating functional component props doesn't change styling 【发布时间】:2020-04-28 15:58:07 【问题描述】:

我有这个函数组件用于将跨度呈现为条形。当我渲染组件时,我将 scrolled 作为 false 传递。然后,当我滚动 150 像素时,jQuery 将属性更新为 true。我知道使用 jQuery 不是一个好习惯,我正在从中迁移。目前,我想让它发挥作用,因为我仍在学习功能组件。

export default function Button(props) 
  const [scrolled, setScrolled] = useState( props.scrolled );
  useEffect(() => 
    setScrolled(props.scrolled);
  , [scrolled]);

  return (
    <HamburgerButton scrolled=scrolled>
      <p>scrolled</p> 
      <span></span>
    </HamburgerButton>
  );

还有这个样式化的组件定义:

const HamburgerButton = styled.div`
  ...
  span 
        background: $props => props.scrolled === 'false' ? props.theme.white : props.theme.black;
  
  ...
`;

当我滚动时,我看到属性 scrolled 在 DOM 中从“假”变为“真”,但跨度保持白色。此外,带有scrolled 的段落标签不会从false 更改。

【问题讨论】:

您正在使用 === 进行严格的相等性检查,但是将布尔值与字符串进行比较,因此它们永远不会相等。应该只是props.scrolled === false @Jayce444 实现此更改使元素保持白色,并且在scrolled 属性更改时不会更改。看来,当 jQuery 更改属性时,它会将布尔值转换为字符串。 @Casey !props.scrolled || props.scrolled === 'false' ? props.theme.white : props.theme.black?涵盖两种情况 我试过background: $props =&gt; !props.scrolled || props.scrolled === false ? props.theme.white : props.theme.black;,但是当scrolled="true"作为组件的属性应用时,它仍然没有更新颜色。 反应钩子的目的是什么?似乎您可以将props.scrolled 直接传递给HamburgerButton。您所做的只是将初始 props.scrolled 值保存在状态中,并在第一次调用效果时使用相同的值更新它,并且没有其他任何东西会更改 scrolled 的值以再次触发效果。 【参考方案1】:

问题 您的代码会记住挂钩中的 props.scrolled 值。

export default function Button(props) 
  const [scrolled, setScrolled] = useState( props.scrolled ); // state initialized
  useEffect(() =>  // hook called first render
    setScrolled(props.scrolled); // state updated with same value
  , [scrolled]); // state value never changes during life of component so effect hook never recomputes

  return (
    <HamburgerButton scrolled=scrolled>
      <p>scrolled</p> 
      <span></span>
    </HamburgerButton>
  );

解决方案 您可以直接将 prop 传递给 HamburgerButton

export default function Button(props) 
  return (
    <HamburgerButton scrolled=props.scrolled>
      <p>props.scrolled</p> 
      <span></span>
    </HamburgerButton>
  );

或者使用钩子并使用正确的依赖项

export default function Button(props) 
  const [scrolled, setScrolled] = useState( props.scrolled );
  useEffect(() => 
    setScrolled(props.scrolled); // update state
  , [props.scrolled]); // with the value that changes here

  return (
    <HamburgerButton scrolled=scrolled>
      <p>scrolled</p> 
      <span></span>
    </HamburgerButton>
  );

对三元组的真分支使用正向比较,并利用 javascript 的真/假值。如果 scrolledtrue 或任何其他真值,则渲染黑色,如果是 fasley,则 (false, 0, null, undefined) 渲染白色。

const HamburgerButton = styled.div`
  ...
  span 
    background: $props => props.scrolled ? props.theme.black : props.theme.white;
  
  ...
`;

const HamburgerButton = styled.div`
  ...
  span 
    background: $props => props.theme[props.scrolled ? 'black' : 'white'];
  
  ...
`;

【讨论】:

嘿!非常感谢您的深入回答。我试过你的解决方案和无骰子;所以,我去用 React Webtools 检查了状态。我看到组件的道具没有更新!原来,我没有实现,或者我忘记了我是如何使用 jQuery 实现 props 的更改的。所以,我去学习了如何创建一个事件侦听器,用于在用户滚动时滚动和更新状态。这与您的解决方案最终像魅力一样工作!感谢您提供多种实施方案,非常彻底!

以上是关于更新功能组件道具不会改变样式的主要内容,如果未能解决你的问题,请参考以下文章

高阶组件状态正在正确更新,但接收道具的包装组件不会在状态更改时重新渲染

Vue JS - 使用异步功能时道具数据不会在孩子中更新

React-Router-DOM 中的 NavLink 组件不接受带有功能的样式道具

避免直接改变道具(渲染功能)

如何将道具从功能组件传递到类组件

更新道具时反应本机组件不透明度不更新