The reason the component is not rendering after the change is because of real nature of Objects, Arrays are Objects in javascript and comparisms is done by object reference not the content of the object For Example
const a = ['a','b','c','d','e']
// comparing a to itself is true
console.log(a === a) // This line returns true
const b = a;
console.log(a === b) // this line returns true because they both point to the same reference
// =========================NOW CONSIDER THIS EXAMPLE=========================================
const c = ['a','b','c'];
const d = ['a','b','c'];
console.log(c === d) // This will return false because they point to different object even though their content is the same
// NOW CONSIDER THIS
const e = [...c,'e'];
const h = Object.assign([],c);
h.push('e');
const f = c;
f.push('e');
console.log(e === c ) // false
console.log(f === c ) // true
console.log(f === h ) // false
For react to rerender the previous state must not be equal to the present state and since you are using array on the state the above shows that we have to return a new array and modifying your code i will just change one line and code will work fine
Your code modified(only one line)
import React, { useState } from "react";
import {
Button,
Text
} from "@chakra-ui/react"
function Hi () {
const [urls, setUrls] = useState([]);
return (
<div>
<Button onClick={(e) => {
let url_list = Object.assign([],urls); // copys urls to new array and returns new array to url_list
url_list.push("hi");
setUrls(url_list);
}}
>
Push
</Button>
{urls.map(item => (
<Text>{item}</Text>
))}
</div>
)
}