Why I can not re-render a component when click on Menu item sort

59 views Asked by At

This is my code, I have a list Contacts to render view ListContact, in that view, I have Menu sort have 2 item: "Tên(A-Z)" to inscrease and "Tên(Z-A)" to descrease and list.map. Why I can not re-render that view when click on Menu item sort. I tried to use UseState and UseEffect but it not work. I use menu of @headlessui/react.

function ViewListFriend() {

    const [contacts, setContacts] = useState([....]);

    contacts.sort((a, b) => a.name.localeCompare(b.name));
    const [selectedOptionName, setSelectedOptionName] = useState('ins');

    useEffect(() => {
        // const sortedContacts = [...contacts].sort((a, b) => {
        //     if (selectedOptionName === 'ins') {
        //         return a.name.localeCompare(b.name);
        //     } else {
        //         return b.name.localeCompare(a.name);
        //     }
        // });
        // setContacts(sortedContacts);
    }, [selectedOptionName]);

    function ListContact({ list }) {
        return (

            <Menu as="div">
                <div>
                    <Menu.Button>
                        <p>{selectedOptionName === 'ins' ? 'Tên(A-Z)' : 'Tên (Z-A)'}</p>
                    </Menu.Button>
                </div>
                <Menu.Items>
                    <div>
                        <Menu.Item>
                            {({ active }) => (
                                <button
                                    onClick={() => {
                                        setSelectedOptionName('ins')
                                        const sortedContacts = [...contacts].sort((a, b) => a.name.localeCompare(b.name));
                                        setContacts(sortedContacts);
                                    }}>
                                    Tên (A-Z)
                                </button>
                            )}
                        </Menu.Item>
                        <Menu.Item>
                            {({ active }) => (
                                <button
                                    onClick={() => {
                                        setSelectedOptionName('des')
                                        const sortedContacts = [...contacts].sort((b, a) => a.name.localeCompare(b.name));
                                        setContacts(sortedContacts);
                                    }}>
                                    Tên (Z-A)
                                </button>
                            )}
                        </Menu.Item>
                    </div>
                </Menu.Items>
            </Menu>    

            {
            list.map(item => (
                ...render item
            ))
        }
        </div >
    )
    }

    return (
        <div className="flex flex-1 flex-col">
            <ListContact list={contacts} />
        </div>
    )
}
export default ViewListFriend;

How to render a view when click on Menu item.

1

There are 1 answers

0
Liap On BEST ANSWER

In your code. The reason why the sort function does not work is every time you click on sort button Tên (A-Z) or Tên (Z-A)

The component will rerender and this line will run again

contacts.sort((a, b) => a.name.localeCompare(b.name));

and the result will always be affected by the first sorted

Try this

import React, { useState } from 'react';


export function App(props) {
  const [contacts, setContacts] = useState([{ name: "b" }, { name: "a" }, { name: "c" }]);
  const [selectedOptionName, setSelectedOptionName] = useState('ins');

  function ListContact({ list }) {
    return (
      <div>
        <div>
          <div>
            <button>
              <p>{selectedOptionName === 'ins' ? 'Tên(A-Z)' : 'Tên (Z-A)'}</p>
            </button>
          </div>
          <div>
            <div>
              <div>
                <button
                  onClick={() => {
                    setSelectedOptionName('ins')
                    const sortedContacts = [...contacts].sort((a, b) => a.name.localeCompare(b.name));
                    setContacts(sortedContacts);
                  }}>
                  Tên (A-Z)
                </button>
              </div>
              <div>
                <button
                  onClick={() => {
                    setSelectedOptionName('des')
                    const sortedContacts = [...contacts].sort((b, a) => a.name.localeCompare(b.name));
                    setContacts(sortedContacts);
                  }}>
                  Tên (Z-A)
                </button>
              </div>
            </div>
          </div>
        </div>
        {list.map((item, index) => <p key={index} style={{ color: 'red' }}>{item.name}</p>)}
      </div>
    )
  }

  return (
    <div className="flex flex-1 flex-col">
      <ListContact list={contacts} />
    </div>
  );
}