在useEffect()问题中使用setState进行反应



N.B.我在这里得到了答案,但这不是这个线程的重复问题

我正在尝试从一个具有API的可重用函数中获取数据。这是我的代码

usaData.js在另一页中

const useData = () => {
const [data, setData] = useState([]);
const fetchData = async (url, query, variable) => {
const queryResult = await axios.post(url, {
query: query,
variables: variable,
});
setData(queryResult.data.data);
};

return {data, fetchData}
};

我正在从MainPage.js文件中检索数据

export const MainPage = props => {
const [state, setState] = useState({
pharam: 'Yes',
value: '',
});
const [field, setField] = useState([])
const {data, fetchData} = useData()
const onClick = (event) => {
setState({ ...state, pharam: '', value: event });
fetchData(url, query, event)
setField(data)
}
return (
<div>
...
<Select
placeholder='select'
>
{field.map(item => (
<Select.Option key={item.name}>
{item.name}
</Select.Option>
))}
</Select>
<Button onClick={onClick}>Change Select</Button>
...
</div>
)
}

问题是onClick函数中的setField(data)没有立即更新,因为它是一个异步调用。因此,我尝试使用一个函数作为第二个参数

...
setField(data, () => {
console.log(data)
})
...

它以红色返回以下警告,但行为与之前类似,没有立即更新数据。

警告:来自useState((和useReducer((挂钩的状态更新不支持第二个回调参数。要在渲染后执行副作用,请使用useEffect((在组件主体中声明它。

根据警告,我尝试在onClick函数中使用useEffect()

...
const onClick = (event) => {
setState({ ...state, pharam: '', value: event });
useEffect(() => {
fetchData(url, query, event)
setField(data)
}, [data])
}
...

返回错误

React Hook"useEffect";在函数"中被调用;onClick"既不是React函数组件,也不是自定义React Hook函数。React组件名称必须以大写字母开头。React Hook名称必须以单词"开头;使用";

我必须在哪里进行更改?由于setField将立即更新field,我如何获得预期行为?

我的建议是不要在自定义挂钩中设置State,而不是返回promise。

usaData.js

const useData = () => {
const fetchData = async (url, query, variable) => {
return await axios.post(url, {
query: query,
variables: variable,
});
};
return { fetchData };
};

在MainPage.js中

现在,当您触发onClick函数时,只需使用wait或then语法调用fetchData函数,在成功调用api后,您将在newData变量中返回结果,您可以使用它来更新状态。

注意:这将为您节省额外的useEffect。

export const MainPage = (props) => {
const [state, setState] = useState({
pharam: "Yes",
value: "",
});
const [field, setField] = useState([]);
const { fetchData } = useData();
const onClick = async (event) => {
setState({ ...state, pharam: "", value: event });
let newData = await fetchData(url, query, event);
console.log("===>", newData.data.data);
setField(newData.data.data);
};
return (
<div>
...
<Select placeholder="select">
{field.map((item) => (
<Select.Option key={item.name}>{item.name}</Select.Option>
))}
</Select>
<Button onClick={onClick}>Change Select</Button>
...
</div>
);
};

您的案例中的问题是setField在获取数据之前得到调用。

因此,您可以有一个useEffect,每次更改data时都会执行它。

useEffect(() => {
if(data.length > 0) {
setField(data);
}
}, [data])

const onClick = (event) => {
setState(prev => ({ ...prev, pharam: '', value: event }));
fetchData(url, query, event);
}

据我所知,React异步设置其状态。因此,为了更新状态字段,您需要一个useEffect钩子。您的useEffect方法是正确的,只是它需要放置在Click外部(直接在组件函数中(。

export const MainPage = () => {
...
useEffect(() => {
setField(data)
},[data])
...
}

相关内容

  • 没有找到相关文章

最新更新