Home > Enterprise >  How can I truncate text of a specific element inside .map function in React?
How can I truncate text of a specific element inside .map function in React?

Time:12-06

const { useEffect, useState } = React;

function App() {
  const [data, setData] = useState([]);
  const [show, setShow] = useState(false)

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then((response) => response.json())
      .then((res) => setData(res))
      .catch((err) => console.log("error", err.message))
  }, [])

  let showNames = (users, index) => {
    return (
      <h3 key={index} onm ouseOver={() => setShow(true)} onm ouseLeave={() => setShow(false)}>
        {show ? users.name : `${users.name.substring(0, 5)}...`}
      </h3>
    )
  }

  return (
    <div className="App">
      <header className="App-header">
        {
          data && data.map((users, index) => {
            return (
              showNames(users, index)
            )
          })
        }
      </header>
    </div>
  );
}

ReactDOM.createRoot(document.body).render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

I'm currently learning ReactJS, and I am facing an issue while trying to hide/show truncated text. The following code is working, but when I hover over the text it truncates every name from the list. I would instead like it to show/hide the name only where I hover.

CodePudding user response:

Your problem is that you only have one show state that controls the visibility of all your text items. There are a few options to fix this, one way would be to .map() the data you get from your API to include a show property, which you can update for particular objects within data when you hover over the associated item. This option is good if you need multiple options expanded at the same time, however, with your current set up you can only have one item expanded (by the nature of your mouse enter/leave to toggle the expanded state). The other option to deal with this is to store the id of the currently expanded item, and then within your .map() only expand the item if the item id matches the stored id within your state.

See working example below:

const { useEffect, useState } = React;

function App() {
  const [data, setData] = useState([]);
  const [showId, setShowId] = useState(-1); // invalid id that matches no users

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then((response) => response.json())
      .then((res) => setData(res))
      .catch((err) => console.log("error", err.message))
  }, [])

  let showNames = user => {
    return (
      <h3 key={user.id} onm ouseOver={() => setShowId(user.id)} onm ouseLeave={() => setShowId(-1)}>
        {showId === user.id ? user.name : `${user.name.substring(0, 5)}...`}
      </h3>
    )
  }

  return (
    <div className="App">
      <header className="App-header">
        {
          data && data.map(user => showNames(user))
        }
      </header>
    </div>
  );
}

ReactDOM.createRoot(document.body).render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

I've also updated your component to use the user id as the key, without relying on the index (using the index as the key can cause rendering bugs if your users are removed from the list)

CodePudding user response:

you can simply set show status pre user.name and check if users.name is true or not

here is what I did :

const { useEffect, useState } = React;

  
function App() {
  const [data, setData] = useState([]);
  const [show, setShow] = useState({});

  useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
  .then((response) => response.json())
  .then((res) => setData(res))
  .catch((err) => console.log("error", err.message));
  }, []);

  let showNames = (users, index) => {
return (
  <h3
    key={index}
    onm ouseOver={() =>
      setShow((prevState) => ({ ...prevState, [users.name]: true }))
    }
    onm ouseLeave={() =>
      setShow((prevState) => ({ ...prevState, [users.name]: false }))
    }
  >
    {show[users.name] ? users.name : `${users.name.substring(0, 5)}...`}
  </h3>
);
  };

  return (
<div className="App">
  <header className="App-header">
    {data &&
      data.map((users, index) => {
        return showNames(users, index);
      })}
  </header>
</div>
  );
}

ReactDOM.createRoot(document.body).render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

  • Related