React:基于 props 的设置和更新
React: Setting and updating based on props
目前我面临的问题是,我想在 prop 初始化或更改为某个值后立即更改 React 中子组件的状态。如果我用一个简单的 if 查询来解决这个问题,那么我当然会得到一个无限循环,因为组件会被一遍又一遍地渲染。
组件(父):
function App() {
const [activeSlide, setActiveSlide] = useState(0);
function changeSlide(index) {
setActiveSlide(index);
}
return (
<div className="app">
<div className="app__nav">
<Button icon="FiSun" handler={changeSlide} active={activeSlide} index="0" />
<Button icon="FiSettings" handler={changeSlide} active={activeSlide} index="1" />
</div>
</div>
);
}
组件(子):
function Button(props) {
const Icon = Icons[props.icon];
const [activeClass, setActiveClass] = useState("");
// This attempts an endless loop
if(props.active == props.index) {
setActiveClass("active");
}
function toggleView(e) {
e.preventDefault();
props.handler(props.index);
}
return(
<button className={activeClass} data-index={props.index} onClick={toggleView}>
<Icon />
</button>
)
}
这里有一个明智而简单的方法吗?我的想法是将 if-query 写入 return() 并因此生成两个不同的输出,即使我实际上想避免这种情况
尝试使用钩子useEffect来防止无限循环。 (https://fr.reactjs.org/docs/hooks-effect.html)
或者使用回调钩子。 (https://fr.reactjs.org/docs/hooks-reference.html#usecallback)
试试这个,然后告诉我它是否适合你:
function App() {
const [activeSlide, setActiveSlide] = useState(0);
const changeSlide = useCallback(() => {
setActiveSlide(index);
}, [index]);
return (
<div className="app">
<div className="app__nav">
<Button icon="FiSun" handler={changeSlide} active={activeSlide} index="0" />
<Button icon="FiSettings" handler={changeSlide} active={activeSlide} index="1" />
</div>
</div>
);
}
这个用处很大of useEffect。
您可以将 if 语句替换为;
const {active, index} = props
useEffect(_ => {
if(active == index) {
setActiveClass("active");
}
}, [active])
函数中的最后一项是依赖项,所以 useEffect 只会 运行 如果活动道具发生变化。
当状态或道具发生变化时,React 会自动重新渲染组件。如果您只是使用 activeClass
来管理 className
,您可以像这样移动 className
中的条件并摆脱状态。
<button className={props.active === props.index ? 'active' : ''} data-index={props.index} onClick={toggleView}>
<Icon />
</button>
但是,如果您仍想在子组件中使用状态,则可以使用 useEffect
挂钩来更新子组件中的状态。
React 文档有一个很好的清单 here 用于确定某物是否属于状态。这是列表:
- 它是通过道具从 parent 传入的吗?如果是这样,它可能不是状态。
- 它是否随着时间的推移保持不变?如果是这样,它可能不是状态。
- 你能根据组件中的任何其他状态或道具计算它吗?如果是,则不是状态。
活动 class 不符合该标准,应该在需要时计算而不是放入状态。
return(
<button className={props.active == props.index ? 'active' : ''} data-index={props.index} onClick={toggleView}>
<Icon />
</button>
)
目前我面临的问题是,我想在 prop 初始化或更改为某个值后立即更改 React 中子组件的状态。如果我用一个简单的 if 查询来解决这个问题,那么我当然会得到一个无限循环,因为组件会被一遍又一遍地渲染。
组件(父):
function App() {
const [activeSlide, setActiveSlide] = useState(0);
function changeSlide(index) {
setActiveSlide(index);
}
return (
<div className="app">
<div className="app__nav">
<Button icon="FiSun" handler={changeSlide} active={activeSlide} index="0" />
<Button icon="FiSettings" handler={changeSlide} active={activeSlide} index="1" />
</div>
</div>
);
}
组件(子):
function Button(props) {
const Icon = Icons[props.icon];
const [activeClass, setActiveClass] = useState("");
// This attempts an endless loop
if(props.active == props.index) {
setActiveClass("active");
}
function toggleView(e) {
e.preventDefault();
props.handler(props.index);
}
return(
<button className={activeClass} data-index={props.index} onClick={toggleView}>
<Icon />
</button>
)
}
这里有一个明智而简单的方法吗?我的想法是将 if-query 写入 return() 并因此生成两个不同的输出,即使我实际上想避免这种情况
尝试使用钩子useEffect来防止无限循环。 (https://fr.reactjs.org/docs/hooks-effect.html)
或者使用回调钩子。 (https://fr.reactjs.org/docs/hooks-reference.html#usecallback)
试试这个,然后告诉我它是否适合你:
function App() {
const [activeSlide, setActiveSlide] = useState(0);
const changeSlide = useCallback(() => {
setActiveSlide(index);
}, [index]);
return (
<div className="app">
<div className="app__nav">
<Button icon="FiSun" handler={changeSlide} active={activeSlide} index="0" />
<Button icon="FiSettings" handler={changeSlide} active={activeSlide} index="1" />
</div>
</div>
);
}
这个用处很大of useEffect。
您可以将 if 语句替换为;
const {active, index} = props
useEffect(_ => {
if(active == index) {
setActiveClass("active");
}
}, [active])
函数中的最后一项是依赖项,所以 useEffect 只会 运行 如果活动道具发生变化。
当状态或道具发生变化时,React 会自动重新渲染组件。如果您只是使用 activeClass
来管理 className
,您可以像这样移动 className
中的条件并摆脱状态。
<button className={props.active === props.index ? 'active' : ''} data-index={props.index} onClick={toggleView}>
<Icon />
</button>
但是,如果您仍想在子组件中使用状态,则可以使用 useEffect
挂钩来更新子组件中的状态。
React 文档有一个很好的清单 here 用于确定某物是否属于状态。这是列表:
- 它是通过道具从 parent 传入的吗?如果是这样,它可能不是状态。
- 它是否随着时间的推移保持不变?如果是这样,它可能不是状态。
- 你能根据组件中的任何其他状态或道具计算它吗?如果是,则不是状态。
活动 class 不符合该标准,应该在需要时计算而不是放入状态。
return(
<button className={props.active == props.index ? 'active' : ''} data-index={props.index} onClick={toggleView}>
<Icon />
</button>
)