为什么所有的手风琴开关在ReactJs一起?



当我点击+按钮时,我有手风琴,然后所有手风琴一起打开,这里有什么问题?

我的代码:

const questions = [
{
id:1,
question: 'what is the react one',
answer: 'react is a javascript library for building user interfaces for UI components'
},
{
id:2,
question: 'what is the react two',
answer: 'react is a javascript library for building user interfaces for UI components'
},
{
id:3,
question: 'what is the react two',
answer: 'react is a javascript library for building user interfaces for UI components'
},
{
id:4,
question: 'what is the react two',
answer: 'react is a javascript library for building user interfaces for UI components'
},
{
id:5,
question: 'what is the react two',
answer: 'react is a javascript library for building user interfaces for UI components'
},
{
id:6,
question: 'what is the react two',
answer: 'react is a javascript library for building user interfaces for UI components'
},
];
const Accordion = () => {
const [data, setData] = React.useState(questions);
const [show, setShow] = React.useState(false);
return (
<React.Fragment>
<div style={{ padding: "50px" }}>
<h2>Arrordion</h2>
{data.map((curElem) => {
return (
<div>
<div className="main-heading">
<p
style={{ cursor: "pointer" }}
onClick={() => setShow(!show)}
>
+
</p>
<h3>{curElem.question}</h3>
</div>
{show && <p> {curElem.answer}</p>}
<hr />
</div>
);
})}
</div>
</React.Fragment>
);
};
ReactDOM.render(<Accordion/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>

谢谢!

问题出在状态。当你点击任何一个accordian时,状态变为true,并且由于你在所有accordian上使用了相同的状态,所有这些都变为true并因此打开。

解决方案可以是将状态定义为数组:
const [show, setShow] = useState([])

你的函数可以像这样;

{data.map((curElem, i ) => {
return (
<div>
<div className="main-heading">
<p
style={{ cursor: "pointer" }}
onClick={() => setShow(prevState => prevState[i] = !prevState[i])}
>
+
</p>
<h3>{curElem.question}</h3>
</div>
{show[i] && <p> {curElem.answer}</p>}
<hr />
</div>
);
})}

问题是您只有一个标志show作为所有accordion的状态。这就是为什么当你点击一个+按钮时,状态show正在更新为true,并且当你有{show && <p> {curElem.answer}</p>}时,所有的答案都是可见的。

要解决这个问题,您可能需要按照如下所示存储展开的accordion id。

const questions = [{id:1,question:'what is the react one',answer:'react is a javascript library for building user interfaces for UI components'},{id:2,question:'what is the react two',answer:'react is a javascript library for building user interfaces for UI components'},{id:3,question:'what is the react two',answer:'react is a javascript library for building user interfaces for UI components'},{id:4,question:'what is the react two',answer:'react is a javascript library for building user interfaces for UI components'},{id:5,question:'what is the react two',answer:'react is a javascript library for building user interfaces for UI components'},{id:6,question:'what is the react two',answer:'react is a javascript library for building user interfaces for UI components'},];
const { useState, Fragment } = React;
const Accordion = () => {
const [data, setData] = useState(questions);
const [expandedId, setExpandedId] = useState(-1);
return (
<Fragment>
<div style={{ padding: "50px" }}>
<h2>Arrordion</h2>
{data.map((curElem) => {
return (
<div>
<div className="main-heading">
<p
style={{ cursor: "pointer" }}
onClick={() => setExpandedId(curElem.id)}
>
+
</p>
<h3>{curElem.question}</h3>
</div>
{expandedId === curElem.id && <p> {curElem.answer}</p>}
<hr />
</div>
);
})}
</div>
</Fragment>
);
};
ReactDOM.render(<Accordion />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
<div id="react"></div>

如果你想要多个手风琴可以打开或展开,而不是仅仅存储一个项目的id,我们可以有一个ids数组,并使用它来确定是否打开/展开该特定项目,以显示答案。下面是相同的解决方案。

const questions = [{id:1,question:'what is the react one',answer:'react is a javascript library for building user interfaces for UI components'},{id:2,question:'what is the react two',answer:'react is a javascript library for building user interfaces for UI components'},{id:3,question:'what is the react two',answer:'react is a javascript library for building user interfaces for UI components'},{id:4,question:'what is the react two',answer:'react is a javascript library for building user interfaces for UI components'},{id:5,question:'what is the react two',answer:'react is a javascript library for building user interfaces for UI components'},{id:6,question:'what is the react two',answer:'react is a javascript library for building user interfaces for UI components'},];
const { useState, Fragment } = React;
const Accordion = () => {
const [data, setData] = useState(questions);
const [expandedIds, setExpandedIds] = useState([]);
return (
<Fragment>
<div style={{ padding: "50px" }}>
<h2>Arrordion</h2>
{data.map((curElem) => {
return (
<div>
<div className="main-heading">
<p
style={{ cursor: "pointer" }}
onClick={() => setExpandedIds(ids => [...ids, curElem.id])}
>
+
</p>
<h3>{curElem.question}</h3>
</div>
{expandedIds.includes(curElem.id) && <p> {curElem.answer}</p>}
<hr />
</div>
);
})}
</div>
</Fragment>
);
};
ReactDOM.render(<Accordion />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
<div id="react"></div>

注意:我们还可以在点击按钮时切换功能,以便任何手风琴将相应地展开和折叠。

手风琴中每个元素的onClick事件处理程序都在更新相同的状态,即show。所以点击任何一个元素都会打开

另外,由于您正在使用show的先前值来切换状态,因此应该考虑使用回调来设置状态,因为状态更新是异步的。

onClick={() => setShow(show => !show)}

问题是您有一个单独的状态变量来管理它们。你需要更好的控制,需要状态变量,它是一个数组来控制每个单独的项目。

你可以使用以下方法:

  1. 数组状态变量
  2. .map()
  3. 的索引参数
  4. 通过复制数组并更新相关索引来设置状态
import "./styles.css";
import React from "react";
const questions = [
{
id: 1,
question: "what is the react one",
answer:
"react is a javascript library for building user interfaces for UI components"
},
{
id: 2,
question: "what is the react two",
answer:
"react is a javascript library for building user interfaces for UI components"
},
{
id: 3,
question: "what is the react two",
answer:
"react is a javascript library for building user interfaces for UI components"
},
{
id: 4,
question: "what is the react two",
answer:
"react is a javascript library for building user interfaces for UI components"
},
{
id: 5,
question: "what is the react two",
answer:
"react is a javascript library for building user interfaces for UI components"
},
{
id: 6,
question: "what is the react two",
answer:
"react is a javascript library for building user interfaces for UI components"
}
];
export default function App() {
const [data, setData] = React.useState(questions);
const [show, setShow] = React.useState(new Array(data.length).fill(false));
return (
<>
<div style={{ padding: "50px" }}>
<h2>Arrordion</h2>
{data.map((curElem,index) => {
return (
<div>
<div className="main-heading">
<p style={{ cursor: "pointer" }} onClick={() => setShow((show) => { 
let copyShow = [...show];
copyShow[index] = !copyShow[index];
return copyShow;
} )}>
+
</p>
<h3>{curElem.question}</h3>
</div>
{show[index] && <p> {curElem.answer}</p>}
<hr />
</div>
);
})}
</div>
</>
);
}

沙箱

我认为使用活动索引来显示细节将是一个很好的答案。

onClick={() =>
activeIndex === -1
? setActiveIndex(curElem.id)
: setActiveIndex(-1)
}

最新更新