skip to Main Content

From this array [21, 42, 54, 1, 87, 90, 56, 27, 89]

I am displaying first 3 numbers by default
next button want to shift one step and show as 42, 54, 1
on previous button click want to show one step behind it like 21, 42, 54

but I am stuck
please sey by code what I am doing wrong, I am trying to increase the starting initial index number from which 3 numbers will be picked

import React from "react";
import { useState } from "react";
const App = () => {
  const list = [21, 42, 54, 1, 87, 90, 56, 27, 89];

  var start = 0;

  const handleClick = () => {
    start = start + 1;
  };

  var n = 3;

  var items = list.slice(start, n).map((i) => {
    return (
      <button style={{ margin: 10 }} type="button" class="btn btn-primary">
        {i}
      </button>
    );
  });

  return (
    <div>
      <div onClick={handleClick}>Click</div>
      <div>{items}</div>
    </div>
  );
};

export default App;

3

Answers


  1. First, you should store the start index in state.

    const [start, setStart] = useState(0);
    
    const handleClick = () => {
      setStart(start + 1);
    };
    

    In addition, the second argument to slice should be the end index, not the number of elements to take. So the call to Array#slice should be like this:

    list.slice(start, start + n)
    

    Working example:

    const App = () => {
      const list = [21, 42, 54, 1, 87, 90, 56, 27, 89];
      const [start, setStart] = React.useState(0);
      const handleClick = () => {
        setStart(start + 1);
      };
      const n = 3;
      const items = list.slice(start, start + n).map((item, idx) =>
          <button style={{ margin: 10 }} type="button" className="btn btn-primary" key={idx}>
            {item}
          </button>
      );
      return (
        <div>
          <div onClick={handleClick}>Click</div>
          <div>{items}</div>
        </div>
      );
    };
    ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <div id="root"></div>
    Login or Signup to reply.
  2. You cannot use variables like that inside a react component because at every render the value of 0 will be set to your start variable.

    Instead you should use states. See the working example:

    import React from "react";
    import { useState } from "react";
    const App = () => {
      const list = [21, 42, 54, 1, 87, 90, 56, 27, 89];
    
      const [start, setStart] = useState(0);
    
      const handleClick = () => {
        setStart(start+1);
      };
    
      const n = 3;
    
      const items = list.slice(start, start + n).map((i) => {
        return (
          <button style={{ margin: 10 }} type="button" class="btn btn-primary">
            {i}
          </button>
        );
      });
    
      return (
        <div>
          <div onClick={handleClick}>Click</div>
          <div>{items}</div>
        </div>
      );
    };
    
    export default App;

    Note that your slice code was also wrong since you are using a fixed n. Slice parameters are start and end index to slice, so you need to sum start and n.

    Login or Signup to reply.
  3. The key is to store the index in state (const [index, setIndex] = useState(0);), and to use that state to guide how you’re going to slice up the list list.slice(index, index + 3). Remember that how a component is rendered depends on how it "reacts" to changes in state.

    A few additional pointers:

    1. If you’re looking to have previous and next buttons you can implement those quite easily by using your handleClick function to cover both, and toggle the state depending on which button is clicked.

    2. You can disable the buttons when index reaches 0, or index reaches the upper bounds of the list length.

    3. Make sure that any component returned by a mapping process has a key (as shown below) or React will start yelling at you. Normally this key should correspond with an id in the data you’re iterating over. In this case it’s probably ok to use the map index parameter for this purpose (though it generally not recommended. Neither is using uuid FWIW).

    const { useState } = React;
    
    const App = () => {
      
      const list = [21, 42, 54, 1, 87, 90, 56, 27, 89];
    
      const [ index, setIndex ] = useState(0);
    
      const handleClick = (e) => {
        const { value } = e.target;
        if (value === 'prev' && index >= 0) {
          setIndex(prev => prev -= 1);
        }
        if (value === 'next' && index < list.length - 3) {
          setIndex(prev => prev += 1);
        }
      };
    
      var items = list.slice(index, index + 3).map((n, i) => {
        return (
          <button
            key={i}
            style={{ margin: 10 }}
            type="button"
            className="btn btn-primary"
          >{n}
          </button>
        );
      });
    
      return (
        <div>
          <button
            className="direction"
            value="prev"
            type="button"
            disabled={index === 0}
            onClick={handleClick}
          >Prev
          </button>
          <button
            value="next"
            type="button"
            disabled={index === list.length - 3}
            onClick={handleClick}
          >Next
          </button>
          <div>{items}</div>
        </div>
      );
    
    };
    
    const node = document.getElementById('root');
    const root = ReactDOM.createRoot(node);
    root.render(<App />);
    .direction:not(:last-of-type) { margin-right: 0.5rem; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
    <div id="root"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search