我写了一个使用react useHooks动态添加文本并使用useState嵌套的示例。 但是,有一个问题,setState无法正常工作?
当我单击文本时,组件中的setState无效(通常是在当前单击的文本中添加一个类,并在其他文本上删除该类),该怎么办?
下面是具体的代码链接:
https://codesandbox.io/s/nifty-sky-z0p9w?file=/src/App.js
谢谢!
答案 0 :(得分:2)
您的代码中的问题是这样的:
const [activeItem, setActiveItem] = useState(null);
您正在App
级别进行定义。并且您期望它可以在TableCel
中工作,而该TableCel
在另一个具有自己状态的组件中。
更好的方法是将App
的组件App
移出activeItems
并在其中使用状态。如果您需要在setActiveItem
内部使用,请同时通过import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [activeItem, setActiveItem] = useState(null);
const TableCel = (props) => {
const { title } = props;
return <div>{title}</div>;
};
const cell = [
{
key: 1,
header: <TableCel id={1} title={"Header"} />,
render: (cvm) => (
<>
<p>--</p>
</>
)
},
{
key: 2,
header: <TableCel id={2} title={"Header"} />,
render: (cvm) => (
<>
<p>--</p>
</>
)
},
{
key: 3,
header: <TableCel id={3} title={"Header"} />,
render: (cvm) => (
<>
<p>--</p>
</>
)
},
{
key: 4,
header: <TableCel id={4} title={"Header"} />,
render: (cvm) => (
<>
<p>--</p>
</>
)
},
{
key: 5,
header: <TableCel id={5} title={"Header"} />,
render: (cvm) => (
<>
<p>--</p>
</>
)
}
];
const [cellList, addCells] = useState(cell);
const [count, setCount] = useState(6);
// console.log(cellList);
const addCell = (value) => {
const _cell = {
key: value,
header: <TableCel title="Header" id={value} />,
render: (cvm) => (
<>
<p>--</p>
</>
)
};
addCells([...cellList, _cell]);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<button
onClick={() => {
setCount(count + 1);
addCell(count + 1);
}}
>
add li
</button>
<div>
{cellList
.filter((cell) => cell.key < 60)
.map((filteredPerson, index) => (
<li
key={index}
onClick={() => {
setActiveItem(filteredPerson.key);
}}
className={filteredPerson.key === activeItem ? "cel-active" : ""}
>
{filteredPerson.header}
</li>
))}
</div>
</div>
);
}
和jetbrains.exodus.InvalidSettingException: Unknown DataReaderWriterProvider
作为道具。
这是代码:
jetbrains.exodus.InvalidSettingException: Unknown DataReaderWriterProvider: jetbrains.exodus.io.FileDataReaderWriterProvider
at jetbrains.exodus.log.LogConfig.getReaderWriterProvider(LogConfig.java:312)
at jetbrains.exodus.env.Environments.newLogInstance(Environments.kt:85)
at jetbrains.exodus.env.Environments.newLogInstance(Environments.kt:73)
at jetbrains.exodus.env.Environments$newInstance$4.invoke(Environments.kt:45)
at jetbrains.exodus.env.Environments$newInstance$4.invoke(Environments.kt:27)
at jetbrains.exodus.env.Environments.prepare(Environments.kt:112)
at jetbrains.exodus.env.Environments.newInstance(Environments.kt:45)
at jetbrains.exodus.entitystore.PersistentEntityStores.newInstance(PersistentEntityStores.java:64)
以下是演示:https://codesandbox.io/s/morning-cookies-8eud6?file=/src/App.js:0-2086
答案 1 :(得分:1)
之所以不起作用,是因为您正在访问函数内部的activeItem
状态值。不建议在函数内部访问状态,因为即使状态已更新,它也将始终具有初始值。这就是<TableCel>
不重新渲染的原因,因为它不知道activeItem状态已经更改。
我建议您仅访问组件的useEffect()
,useCallback()
,useMemo()
内部和return
语句内部的状态。
例如:
function App() {
const [state, setState] = useState('initial Value')
function someFunction(){
// It's not recommended to access the state inside of this function
// cause the value of the state will always be ('initial Value')
// even if the state were updated
console.log(state)
}
useEffect(()=>{
// It's good if you access the value of the state here
// It will be assured it will always have the updated value
console.log(state)
},[state])
return (
// You can also access the value of the state inside return statement
<>
{console.log(state)}
<SomeComponent props={state}/>
</>
)
}
解决方案:
使用上下文挂钩传递activeItem的状态。这样,
在沙箱链接中看一下这段代码,我是否使用上下文挂钩来解决问题