Gabriel Brito
Gabriel Brito

Reputation: 1208

ReactJS child component not updating after parent's state chaged

I have a component where after clicking a button, the function updates the state (order) which rerenders the componet but updates only the span's text. Shouldn't the 'i tag' be rerendered as well?

const {useState, useEffect} = React;

const SortType = {
  UNSORTERED: { icon: 'fas fa-sort', next: 'ASCENDING' },
  ASCENDING: { icon: 'fas fa-sort-up', next: 'DESCENDING' },
  DESCENDING: { icon: 'fas fa-sort-down', next: 'UNSORTERED' }
}

const Sorter = ({ trigger, sortOrder }) => {
  const [order, setOrder] = useState(SortType.UNSORTERED)

  function onSort() {
    const nSortOrder = SortType[order.next]
    setOrder(nSortOrder)
    trigger(nSortOrder)
  }

  useEffect(() => {
    if (sortOrder) {
      setOrder(sortOrder)
    }
  }, [sortOrder])

  return (
    <button onClick={onSort}>
      <i className={order.icon}/>
      <span>{order.icon}</span>
    </button>
  )
}

ReactDOM.render(
  <Sorter trigger={console.log} sortOrder={SortType.UNSORTERED} />,
  document.getElementById("react")
);
<script src="https://use.fontawesome.com/releases/v5.11.2/js/all.js"></script>
<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>

Actual result vs Expected result

Actual result Expected result

Upvotes: 2

Views: 79

Answers (1)

Loi Nguyen Huynh
Loi Nguyen Huynh

Reputation: 9958

I think the problem is with your font-awesome's cdn link. Because as we've all seen, the value of order.icon did change, the className of the i tag did change, but then it rendered the weird svg component with an unchanged class of "fa-sort". Just replaced with another cdn link of fontawesome here, and it worked properly.

  • The code works properly after replacing one line of code from yours:

const {useState, useEffect} = React;

const SortType = {
  UNSORTERED: { icon: 'fas fa-sort', next: 'ASCENDING' },
  ASCENDING: { icon: 'fas fa-sort-up', next: 'DESCENDING' },
  DESCENDING: { icon: 'fas fa-sort-down', next: 'UNSORTERED' }
}

const Sorter = ({ trigger, sortOrder }) => {
  const [order, setOrder] = useState(SortType.UNSORTERED)

  function onSort() {
    const nSortOrder = SortType[order.next]
    setOrder(nSortOrder)
    trigger(nSortOrder)
  }

  useEffect(() => {
    if (sortOrder) {
      setOrder(sortOrder)
    }
  }, [sortOrder])

  return (
    <button onClick={onSort}>
      <i className={order.icon}></i>
      <span>{order.icon}</span>
    </button>
  )
}

ReactDOM.render(
  <Sorter trigger={console.log} sortOrder={SortType.UNSORTERED} />,
  document.getElementById("react")
);
<!-- REPLACED HERE -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css"> 

<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>

Upvotes: 1

Related Questions