在反应中显示或隐藏特定元素
Show or Hide a particular element in react
我必须显示常见问题解答列表并且我需要隐藏问题的答案。当我单击问题时,需要显示该特定问题的答案。我的问题是,我有一堆问题,当我点击按钮时,它会显示所有答案,而不是该问题的具体答案。
class Faqs extends Component {
constructor(props){
super(props);
this.state = {
isHidden: true
}
}
toggleHidden () {
this.setState({
isHidden: !this.state.isHidden
})
}
render() {
return (
<div>
<span onClick={() => this.toggleHidden()}><strong>This is the question</strong></span>
{!this.state.isHidden && <p>Answer for the question</p>} <br/>
<span onClick={() => this.toggleHidden()}><strong>Question2</strong></span>
{!this.state.isHidden && <p>Answer2</p>} <br/>
<hr></hr>
</div >
)
}
}
我会为答案编写不同的处理程序。将来如果您需要更多逻辑,答案将是可扩展的。注意 renderAnswer
class Faqs extends Component {
constructor(props){
super(props);
this.state = {
isHidden: true
}
}
toggleHidden () {
this.setState({
isHidden: !this.state.isHidden
})
}
renderAnswer() {
if (this.state.isHidden) {
return;
}
return (
<p>Answer</p>
);
}
render() {
return (
<div>
<span onClick={() => this.toggleHidden()}><strong>This is the question</strong></span>
{ this.renderAnswer() } <br/>
<span onClick={() => this.toggleHidden()}><strong>Question2</strong></span>
{ this.renderAnswer() } <br/>
<hr></hr>
</div >
)
}
}
这是另一种方式来做你想做的事。 (这个只能一次打开一个)
class Faqs extends Component {
constructor(props){
super(props);
this.state = {
hiddenId: null,
}
}
setHiddenId(id) {
this.setState({
hiddenId: id
})
}
render() {
return (
<div>
<span onClick={() => this.setHiddenId('one')}><strong>This is the question</strong></span>
{this.state.hiddenId === 'one' && <p>Answer for the question</p>} <br/>
<span onClick={() => this.setHiddenId('two')}><strong>Question2</strong></span>
{this.state.hiddenId === 'two' && <p>Answer2</p>} <br/>
<hr></hr>
</div >
)
}
}
您可以将您的组件分解到更多级别,以获得一个仅呈现问题和相应答案的子组件。将问题和答案作为道具传递。通过这种方式,您可以对所有问题使用相同的组件,但每个 question/answer 对都会有自己的状态。
class Faq extends Component{
state = {isHidden: true}
toggleHidden = ()=>this.setState((prevState)=>({isHidden: !prevState.isHidden}))
render(){
return(
<div>
<span onClick={this.toggleHidden}>
<strong>{props.question}</strong></span>
{!this.state.isHidden && <p>{props.answer}</p>}
</div>
)
}
}
class Faqs extends Component {
render() {
return (
<div>
<Faq question={"Question 1"} answer={"answer 1"} />
<Faq question={"Question 2"} answer={"answer 2"} />
</div >
)
}
}
问题是您正在使用 one 布尔状态块来控制多个块的逻辑。这是使用单独组件的经典场景。
创建一个封装 show/reveal 机制的新组件 ToggleQuestion
。
Faqs
组件改为管理 ToggleQuestion
个组件的列表。
const QUESTIONS = [
{ title: 'q1', answer: 'a1' },
{ title: 'q2', answer: 'a2' }
]
class ToggleQuestion extends React.Component {
constructor (props) {
super(props)
this.state = { isHidden: true }
}
toggleHidden () {
this.setState({ isHidden: !this.state.isHidden })
}
render () {
const { question, answer } = this.props
const { isHidden } = this.state
return (
<div>
<span>{question}</span>
{ !isHidden && <span>{answer}</span> }
<button onClick={this.toggleHidden.bind(this)}>
Reveal Answer
</button>
</div>
)
}
}
class Faqs extends React.Component {
render () {
return (
<div>
{ QUESTIONS.map(question => (
<ToggleQuestion
question={question.title}
answer={question.answer}
/>
))}
</div>
)
}
}
ReactDOM.render(<Faqs />, document.getElementById('container'))
<div id='container'></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
理想情况下,您会在某种列表中列出常见问题解答 - 然后当您遍历它们时,每个都会分配一个索引号 - 然后当您切换各个答案时,您将该索引存储在状态中并对其进行操作DOM 通过那个号码。
编辑。在当今时代,只适合使用钩子来展示示例:
const {useState} = React;
const FaqApp = () => {
const [ selectedQuestion, toggleQuestion ] = useState(-1);
function openQuestion(index) {
toggleQuestion(selectedQuestion === index ? -1 : index);
}
const faqs = getFaqs();
return (
<div>
<h2>FAQs:</h2>
{faqs.map(( { question, answer}, index) => (
<div key={`item-${index}`} className={`item ${selectedQuestion === index ? 'open' : ''}`}>
<p className='question' onClick={() => openQuestion(index)}>{question}</p>
<p className='answer'>{answer}</p>
</div>
))}
</div>
)
}
function getFaqs() {
const faqs = [
{
question: 'Question 1',
answer: 'answer 1'
},
{
question: 'Question 2',
answer: 'answer 2'
}
];
return faqs;
}
ReactDOM.render(
<FaqApp />,
document.getElementById("react")
);
body {
background: #fff;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
h2 {
margin-bottom: 11px;
}
.item + .item {
margin-top: 11px;
}
.question {
font-weight: bold;
cursor: pointer;
}
.answer {
display: none;
}
.open .answer {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
这个post的旧版本:
我写了一个简单的例子,可以让你有多个问题:
class FaqApp extends React.Component {
constructor(props) {
super(props)
this.state = {
// start the page with all questions closed
selectedQuestion: -1
};
this.openQuestion = this.openQuestion.bind(this);
}
getFaqs() {
// some service returning a list of FAQs
const faqs = [
{
question: 'Question 1',
answer: 'answer 1'
},
{
question: 'Question 2',
answer: 'answer 2'
}
];
return faqs;
}
openQuestion(index) {
// when a question is opened, compare what was clicked and if we got a match, change state to show the desired question.
this.setState({
selectedQuestion: (this.state.selectedQuestion === index ? -1 : index)
});
}
render() {
// get a list of FAQs
const faqs = this.getFaqs();
return (
<div>
<h2>FAQs:</h2>
{faqs.length && faqs.map((item, index) => (
<div key={`item-${index}`} className={`item ${this.state.selectedQuestion === index ? 'open' : ''}`}>
<p className='question' onClick={() => this.openQuestion(index)}>
{item.question}
</p>
<p className='answer'>
{item.answer}
</p>
</div>
))}
</div>
)
}
}
ReactDOM.render(<FaqApp />, document.querySelector("#app"))
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
h2 {
margin-bottom: 11px;
}
.item + .item {
margin-top: 11px;
}
.question {
font-weight: bold;
cursor: pointer;
}
.answer {
display: none;
}
.open .answer {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
我必须显示常见问题解答列表并且我需要隐藏问题的答案。当我单击问题时,需要显示该特定问题的答案。我的问题是,我有一堆问题,当我点击按钮时,它会显示所有答案,而不是该问题的具体答案。
class Faqs extends Component {
constructor(props){
super(props);
this.state = {
isHidden: true
}
}
toggleHidden () {
this.setState({
isHidden: !this.state.isHidden
})
}
render() {
return (
<div>
<span onClick={() => this.toggleHidden()}><strong>This is the question</strong></span>
{!this.state.isHidden && <p>Answer for the question</p>} <br/>
<span onClick={() => this.toggleHidden()}><strong>Question2</strong></span>
{!this.state.isHidden && <p>Answer2</p>} <br/>
<hr></hr>
</div >
)
}
}
我会为答案编写不同的处理程序。将来如果您需要更多逻辑,答案将是可扩展的。注意 renderAnswer
class Faqs extends Component {
constructor(props){
super(props);
this.state = {
isHidden: true
}
}
toggleHidden () {
this.setState({
isHidden: !this.state.isHidden
})
}
renderAnswer() {
if (this.state.isHidden) {
return;
}
return (
<p>Answer</p>
);
}
render() {
return (
<div>
<span onClick={() => this.toggleHidden()}><strong>This is the question</strong></span>
{ this.renderAnswer() } <br/>
<span onClick={() => this.toggleHidden()}><strong>Question2</strong></span>
{ this.renderAnswer() } <br/>
<hr></hr>
</div >
)
}
}
这是另一种方式来做你想做的事。 (这个只能一次打开一个)
class Faqs extends Component {
constructor(props){
super(props);
this.state = {
hiddenId: null,
}
}
setHiddenId(id) {
this.setState({
hiddenId: id
})
}
render() {
return (
<div>
<span onClick={() => this.setHiddenId('one')}><strong>This is the question</strong></span>
{this.state.hiddenId === 'one' && <p>Answer for the question</p>} <br/>
<span onClick={() => this.setHiddenId('two')}><strong>Question2</strong></span>
{this.state.hiddenId === 'two' && <p>Answer2</p>} <br/>
<hr></hr>
</div >
)
}
}
您可以将您的组件分解到更多级别,以获得一个仅呈现问题和相应答案的子组件。将问题和答案作为道具传递。通过这种方式,您可以对所有问题使用相同的组件,但每个 question/answer 对都会有自己的状态。
class Faq extends Component{
state = {isHidden: true}
toggleHidden = ()=>this.setState((prevState)=>({isHidden: !prevState.isHidden}))
render(){
return(
<div>
<span onClick={this.toggleHidden}>
<strong>{props.question}</strong></span>
{!this.state.isHidden && <p>{props.answer}</p>}
</div>
)
}
}
class Faqs extends Component {
render() {
return (
<div>
<Faq question={"Question 1"} answer={"answer 1"} />
<Faq question={"Question 2"} answer={"answer 2"} />
</div >
)
}
}
问题是您正在使用 one 布尔状态块来控制多个块的逻辑。这是使用单独组件的经典场景。
创建一个封装 show/reveal 机制的新组件 ToggleQuestion
。
Faqs
组件改为管理 ToggleQuestion
个组件的列表。
const QUESTIONS = [
{ title: 'q1', answer: 'a1' },
{ title: 'q2', answer: 'a2' }
]
class ToggleQuestion extends React.Component {
constructor (props) {
super(props)
this.state = { isHidden: true }
}
toggleHidden () {
this.setState({ isHidden: !this.state.isHidden })
}
render () {
const { question, answer } = this.props
const { isHidden } = this.state
return (
<div>
<span>{question}</span>
{ !isHidden && <span>{answer}</span> }
<button onClick={this.toggleHidden.bind(this)}>
Reveal Answer
</button>
</div>
)
}
}
class Faqs extends React.Component {
render () {
return (
<div>
{ QUESTIONS.map(question => (
<ToggleQuestion
question={question.title}
answer={question.answer}
/>
))}
</div>
)
}
}
ReactDOM.render(<Faqs />, document.getElementById('container'))
<div id='container'></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
理想情况下,您会在某种列表中列出常见问题解答 - 然后当您遍历它们时,每个都会分配一个索引号 - 然后当您切换各个答案时,您将该索引存储在状态中并对其进行操作DOM 通过那个号码。
编辑。在当今时代,只适合使用钩子来展示示例:
const {useState} = React;
const FaqApp = () => {
const [ selectedQuestion, toggleQuestion ] = useState(-1);
function openQuestion(index) {
toggleQuestion(selectedQuestion === index ? -1 : index);
}
const faqs = getFaqs();
return (
<div>
<h2>FAQs:</h2>
{faqs.map(( { question, answer}, index) => (
<div key={`item-${index}`} className={`item ${selectedQuestion === index ? 'open' : ''}`}>
<p className='question' onClick={() => openQuestion(index)}>{question}</p>
<p className='answer'>{answer}</p>
</div>
))}
</div>
)
}
function getFaqs() {
const faqs = [
{
question: 'Question 1',
answer: 'answer 1'
},
{
question: 'Question 2',
answer: 'answer 2'
}
];
return faqs;
}
ReactDOM.render(
<FaqApp />,
document.getElementById("react")
);
body {
background: #fff;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
h2 {
margin-bottom: 11px;
}
.item + .item {
margin-top: 11px;
}
.question {
font-weight: bold;
cursor: pointer;
}
.answer {
display: none;
}
.open .answer {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
这个post的旧版本:
我写了一个简单的例子,可以让你有多个问题:
class FaqApp extends React.Component {
constructor(props) {
super(props)
this.state = {
// start the page with all questions closed
selectedQuestion: -1
};
this.openQuestion = this.openQuestion.bind(this);
}
getFaqs() {
// some service returning a list of FAQs
const faqs = [
{
question: 'Question 1',
answer: 'answer 1'
},
{
question: 'Question 2',
answer: 'answer 2'
}
];
return faqs;
}
openQuestion(index) {
// when a question is opened, compare what was clicked and if we got a match, change state to show the desired question.
this.setState({
selectedQuestion: (this.state.selectedQuestion === index ? -1 : index)
});
}
render() {
// get a list of FAQs
const faqs = this.getFaqs();
return (
<div>
<h2>FAQs:</h2>
{faqs.length && faqs.map((item, index) => (
<div key={`item-${index}`} className={`item ${this.state.selectedQuestion === index ? 'open' : ''}`}>
<p className='question' onClick={() => this.openQuestion(index)}>
{item.question}
</p>
<p className='answer'>
{item.answer}
</p>
</div>
))}
</div>
)
}
}
ReactDOM.render(<FaqApp />, document.querySelector("#app"))
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
h2 {
margin-bottom: 11px;
}
.item + .item {
margin-top: 11px;
}
.question {
font-weight: bold;
cursor: pointer;
}
.answer {
display: none;
}
.open .answer {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>