Kurona
Kurona

Reputation: 15

How to call same function in multiple div in React?

<button className="readlink" onClick={this.moreToggle}>Read {this.state.expanded ? 'Less' : 'More'}...</button>

moreToggle = () => {
        if(this.state.isExpanded == 'ansText'){
            this.setState({isExpanded: 'ansText ansTextExpanded'});
            this.setState({expanded: true});
        }
        else{
            this.setState({isExpanded: 'ansText'});
            this.setState({expanded: false});
        }
    }

I have this function moreToggle which needs to be called only for the specific div where user clicks. There are more than 1 div like this but using the above approach all div are toggled. How can this be achieved.

<div className="quesData ansData">
                        <div className="quesText">Does weighted blanket helps to reduce stress?</div>
                        <div className="askedDate">Asked on January 14, 2020</div>
                        <div className={this.state.isExpanded}>
                            Weighted blankets Weighted blankets Weighted blankets Weighted blankets Weighted blankets
                            Weighted blankets Weighted blankets Weighted blankets Weighted blankets Weighted blankets
                            Weighted blankets Weighted blankets Weighted blankets Weighted blankets Weighted blankets
                            Weighted blankets Weighted blankets Weighted blankets Weighted blankets Weighted blankets
                            Weighted blankets Weighted blankets Weighted blankets Weighted blankets Weighted blankets
                            Weighted blankets Weighted blankets Weighted blankets Weighted blankets Weighted blankets
                            Weighted blankets Weighted blankets Weighted blankets Weighted blankets Weighted blankets
                            Weighted blankets Weighted blankets Weighted blankets Weighted blankets Weighted blankets
                            Weighted blankets Weighted blankets Weighted blankets Weighted blankets Weighted blankets
                        </div>
                        <button className="readlink" onClick={this.moreToggle}>Read {this.state.expanded ? 'Less' : 'More'}...</button>
                    </div>

The button is used to expand the div by adding class to the content div i.e. weighted blankets div.

Upvotes: 1

Views: 227

Answers (3)

Morteza Ebrahimi
Morteza Ebrahimi

Reputation: 760

If you have an array of object(from api), then you can add another property to each item for expanding:

import React, { useState } from "react";

export default function App() {
  // for example array of object received from api
  const [state,setState]=useState([{id:1,title:"first"},{id:2,title:"second"}]);

  const moreToggle=(id)=>{
    let result=state.find(item=>item.id===id);
    // add isExpanded property to each item of array or change it
    // now each item of array is like this: {id:1,title:"first", isExpanded:true or false}
    result.isExpanded=!result.isExpanded;
    setState([...state]);
  }

  return (
    <div>
      {state.map(item=>
      <div>
        <div className={item.isExpanded ? "show":"hidden"}>your {item.title} div</div>
        <button onClick={()=> moreToggle(item.id)}>Read {item.isExpanded ? 'Less' : 'More'}...</button>
      </div>
      )}
    </div>
  );
}

Upvotes: 0

Mujibur Rehman Ansari
Mujibur Rehman Ansari

Reputation: 663

Try this, I have added name attribute to each clickable and in click handle I have passed the sytheticEvent which will give us the clicked elements name back.

import React, { useCallback, useState } from "react";
import "./styles.css";

export default function App() {
  const [myState, setMyState] = useState({});
  const moreToggle = useCallback((e) => {
    const name = e.currentTarget.name;
    console.log(name);

    setMyState(prevState => ({
      ...prevState,
      [name]: !prevState[name],
    }))
  }, []);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      <button className="readlink" name="btn1" onClick={moreToggle}>
        Read {myState.btn1 ? "Less" : "More"}...
      </button>

      <button className="readlink" name="btn2" onClick={moreToggle}>
        Read {myState.btn2 ? "Less" : "More"}...
      </button>
    </div>
  );
}

Upvotes: 0

Thanh Le Hai Hoang
Thanh Le Hai Hoang

Reputation: 1401

You can assign each <div> an id like "div-1", in this case I use an enum: collapsibleFields.FIELD_1 and passed to the moreToggle function and change our state to key-value pairs.

state = {
 expanded: {},
 isExpanded: {},
};

const collapsibleFields = {
   FIELD_1 = 'FIELD_1',
   FIELD_2 = 'FIELD_2',
   // etc
}

<button className="readlink" onClick={() => this.moreToggle(collapsibleFields.FIELD_1)}>Read {this.state.expanded[collapsibleFields.FIELD_1] ? 'Less' : 'More'}...</button>
 <div className="quesText">Does weighted blanket helps to reduce stress?</div>
                        <div className="askedDate">Asked on January 14, 2020</div>
                        <div className={this.state.isExpanded[collapsibleFields.FIELD_1]}>
moreToggle = (id) => {
        this.setState({
             expanded[id]: this.state.isExpanded[id] === 'ansText'
      });
    }

Upvotes: 1

Related Questions