程式目的是這樣的,我的規格類型select選單選完後,旁邊的規格名稱會對應出資料庫裡該類型裡面已經設定好的名稱(ex. 我選溫度,旁邊的規格名稱select就會有100, 60, 等可以選,選擇單位,就會有杯、碗 等可以選)。
現在遇到狀況一樣式規格select選擇了,程式碼是有跑setState了,但是旁邊的名稱select選單沒有render所以看到的選項還是上一次選擇的內容。
程式碼如下:
<Select
value={type}
onChange={handleChangeSelect} >
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={'1'}>單位</MenuItem>
<MenuItem value={'2'}>溫度</MenuItem>
<MenuItem value={'3'}>糖分</MenuItem>
<MenuItem value={'4'}>加料</MenuItem>
</Select>
const handleChangeSelect = (event) => {
setType(event.target.value);
fetchSpecification(type); //這個type就是上面那行set的那個
};
fetchSpecification(type)的定義方式
async function fetchSpecification(type) {
let config = {
headers: {
'Content-Type': "application/json",
}
} //config
try{
const response = await Axios.post(SPECIFICATION_URL,
{ specificType: type }, config);
setSpecList(response.data.data); //這裡data回傳是一個包很多物件的陣列
}catch(e){
console.log("抓取錯誤:" + e);
}
}
4.第二欄規格名稱的select用的specList定義
const [specList, setSpecList] = useState([]);
//預設值一個空陣列,上面回傳的直接用set蓋掉
5.規格名稱的select
{specList.map((s) => (
<MenuItem value={s.specificType}>{s.specificName}</MenuItem>
))}
這個問題真的爬了很久的文,國內國外都有,但很多都是解釋setState為什麼不立即刷新的原理,沒有講一個正確或立即的方法(該不會React沒有吧....),大多講的是用useEffect監控某個值改變就去刷新,但那個刷新還是要重抓一次全部頁面的資料,好像都沒有一個正規的方式就是“我要的很簡單,setState完值就立即對對應的DOM節點刷新”這樣....
(Vue好像有個雙向綁定可以達成,但我不喜歡Vue的code排列方式XD....
還懇請大佬們指點一下你們遇到此問題的解決方式,感激不盡!!
這個問題我也有碰過,也看過很多說法像是 useState 是非同步的
然後還有看到文章寫說跟 queue 有關,某些事情執行完才會更新 state 的值
還有 closure 有關的@@,忘記哪裡看到的
我後來是用這個套件解決,你可以用看看
https://github.com/Aminadav/react-useStateRef#readme
Select 取值是從 Select 而不是從MenuItem
MenuItem上的value會是傳輸的值
嗯嗯!感謝大大,我那裡是要做傳輸值沒錯,目前call的function都沒問題,就只有規格名稱那裡因為是用specList這個陣列的狀態去map出來的選項,但是因為React setState後他不會立即render所以我的specList一直都是前一次的狀態。
https://codesandbox.io/s/dank-sun-9mebv?file=/src/App4.js
用Select 帶值到Axios在map 到畫面 是沒問題的
用useEffect的話
感謝大大的範例,原來是這樣!!
不懂為什麼這樣不能用useEffect
怕useEffect的影響的層級太大
不就specSelect另外切成一個component
在裡面useEffect dependencies放從prop來的type就好
用useEffect
很方便,有驅動re-render才會進行資料抓取
https://codesandbox.io/embed/react-hooks-counter-demo-forked-yreii?fontsize=14&hidenavigation=1&theme=dark