javascript - 添加渲染表单时出现错误“无效的钩子调用”
问题描述
我试图在两个单选按钮上使用状态,当您选择每个按钮时呈现不同的表单,但是当我尝试添加地图以咨询地址时,会出现此无效的挂钩调用,我不知道如何解决此问题。这是代码
const Pointer = () => (
<img id="pointer" alt="ícone localização" src={pinterIcon} alt="Pointer" />
)
const [mask, setMask] = useState('999.999.999-999')
const [maskPhone, setMaskPhone] = useState('(99) 9999-99999')
const [phone, updatePhone] = useState('')
const [address, updateAddress] = useState('')
const [coordinates, updateCoordinates] = useState([0, 0])
const GOOGLE_MAPS_API_URL =
'https://maps.googleapis.com/maps/api/geocode/json'
function getAddressByCoordinates(latitude, longitude) {
axios
.get(
`${GOOGLE_MAPS_API_URL}?address=${latitude}+${longitude}&key=${process.env.GATSBY_GOOGLE_MAPS_API_KEY}`
)
.then(response => {
const { results } = response.data
if (results.length === 0) return
updateAddress(results[0].formatted_address)
})
}
useEffect(() => {
navigator.geolocation.getCurrentPosition(position => {
const { latitude, longitude } = position.coords
updateCoordinates([latitude, longitude])
getAddressByCoordinates(latitude, longitude)
})
}, [])
async function handleSubmit(event) {
event.preventDefault()
const response = await api.post('clients', {
address,
latitude: coordinates[0],
longitude: coordinates[1],
})
}
async function handleMapClick(event) {
updateCoordinates([event.lat, event.lng])
getAddressByCoordinates(event.lat, event.lng)
}
function handleGetCoordinates() {
if (address.length > 0) {
axios
.get(
`${GOOGLE_MAPS_API_URL}?address=${address}&key=${process.env.GATSBY_GOOGLE_MAPS_API_KEY}`
)
.then(response => {
const { results } = response.data
if (results.length === 0) return
updateAddress(results[0].formatted_address)
updateCoordinates([
results[0].geometry.location.lat,
results[0].geometry.location.lng,
])
})
}
}
const handleValidadePhone = event => {
const { value } = event.target
if (value.length > 14) {
setMaskPhone('(99) 99999-9999')
} else {
setMaskPhone('(99) 9999-99999')
}
updatePhone(value)
}
const handleChangePhone = event => {
updatePhone(event.target.value)
handleValidadePhone(event)
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
internet: ""
};
}
handleChange = (e) => this.setState({ [e.target.name]: e.target.value });
renderForm = () => {
switch (this.state.internet) {
case "residencial":
return (
<form className="form" autoComplete="off">
<div className="input-block">
<label htmlFor="name">Nome</label>
<input
type="text"
name="name"
id="name"
onChange={props.handleChange}
required
/>
</div>
<div className="input-block">
<label htmlFor="email">Email</label>
<input
type="email"
name="email"
id="email"
onChange={props.handleChange}
equired
/>
</div>
<div className="input-block">
<label htmlFor="phone">Telefone</label>
<input
mask={maskPhone}
maskChar=""
type="phone"
name="phone"
id="phone"
onChange={handleChangePhone}
required
/>
</div>
<div className="input-block" id="input">
<label
htmlFor="address"
>
Endereço
</label>
<input
type="text"
id="address"
value={address}
onChange={event => updateAddress(event.target.value)}
onBlur={handleGetCoordinates}
placeholder="Rua, Número, Bairro, Cidade, UF"
required
/>
</div>
<div className="btn-address">
<button
type="submit"
className="address-btn"
>Consultar Endereço
</button>
</div>
<div style={{ height: '430px', width: '100%', marginTop: '20px' }}>
<GoogleMap
bootstrapURLKeys={{
key: 'AIzaSyDRDXI4V6LTjYIZ6rdi5j9soHPCVv_NIl0',
}}
zoom={15}
center={coordinates}
onClick={handleMapClick}
>
<Pointer lat={coordinates[0]} lng={coordinates[1]} />
</GoogleMap>
</div>
</div>
</form>
);
case "empresarial":
return (
<form className="form">
<div>
This one works
</div>
</form>
);
default:
return null;
}
};
render() {
return (
<Container>
<section className="sectio">
<div className="check-blok" onChange={this.onChangeValue}>
<div className="check">
<input
type="radio"
id="residencia"
name="internet"
value="residencial"
onChange={this.handleChange}
/>
<label for="residencial">Internet Residencial</label>
<input
type="radio"
id="empresa"
name="internet"
value="empresarial"
onChange={this.handleChange}
/>
<label for="empresarial">Internet Empresarial</label>
</div>
</div>
<div className="emp-sec">
{this.renderForm()}
</div>
<div className="continue">
<button
className="btn-continue"
onClick={this.handleContinue}
// onClick={props.next}
>
Continuar
</button>
</div>
</section>
</Container>
)
}
}
export default App ;
当我从代码中删除地图及其功能时,它可以工作,但我需要它。也改变了功能,但仍然没有奏效。
解决方案
我想主要问题是你在函数useEffect
内部使用钩子getAddressByCoordinates
。挂钩调用应该发生在组件的根级别。您需要从该功能移出到根级别。
从技术上讲,您违反了Hooks 规则,仅在顶层调用 Hooks:
不要在循环、条件或嵌套函数中调用 Hook。相反,请始终在 React 函数的顶层使用 Hooks。通过遵循此规则,您可以确保每次渲染组件时都以相同的顺序调用 Hook。这就是允许 React 在多个 useState 和 useEffect 调用之间正确保留 Hooks 状态的原因。
推荐阅读
- c - 有没有办法在 Windows 上使用带有 clang 9.0.0 版本的 VS 2010?
- r - 无法编译 test.tex。调试技巧见 https://yihui.name/tinytex/r/#debugging。有关更多信息,请参阅 test.log。执行停止
- python - 圆整数解的算法?
- javascript - 有没有办法在不点击绘图控制器上的“编辑形状”的情况下使用 Leaflet.Draw 编辑传单形状?
- java - 在 Appium 上启动会话时如何解决此错误?
- python - 使用模板覆盖更改 django 管理列表中的模型对象 url
- lsof - 了解 lsof 输出中的 TYPE
- spring - 从需要密钥库的 Springboot 应用程序自动向服务器发送 Post 请求
- jms - 拒绝访问资源:type=
, application=JMSModule, destinationType=queue, resource=test, action=receive - c++ - 意外调用移动构造函数