我想合并多个状态并使用useState
钩子同时处理它们,请检查以下示例,该示例更新了用户输入上的一些文本:
const {useState} = React;
const Example = ({title}) => {
const initialState = {
name: 'John',
age: 25
};
const [{name, age}, setFormState] = useState(initialState);
const handleNameChange = (e) => {
setFormState({
name: e.target.value,
age
});
};
const handleAgeChange = (e) => {
setFormState({
name,
age: e.target.value
})
};
return (
<form onSubmit={e=>e.preventDefault()}>
<input type='text' id='name' name='name' placeholder={name} onChange={handleNameChange} />
<p>The person's name is {name}.</p>
<br />
<label htmlFor='age'>Age: </label>
<input type='text' id='age' name='age' placeholder={age} onChange={handleAgeChange} />
<p>His/her age is {age}.</p>
</form>
);
};
// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<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>
代码运行良好,但是如您所见,我正在使用2个函数分别处理名称和年龄。这与我保存一些代码的意图背道而驰。是否可以仅使用1个功能分别更改姓名和年龄?对此进行了尝试,但显然它将使用相同的值进行更新。
const {useState} = React;
const Example = ({title}) => {
const initialState = {
name: 'John',
age: 25
};
const [{name, age}, setFormState] = useState(initialState);
const handleChange = (e) => {
setFormState({
name: e.target.value,
age: e.target.value
});
};
return (
<form onSubmit={e=>e.preventDefault()}>
<input type='text' id='name' name='name' placeholder={name} onChange={handleChange} />
<p>The person's name is {name}.</p>
<br />
<label htmlFor='age'>Age: </label>
<input type='text' id='age' name='age' placeholder={age} onChange={handleChange} />
<p>His/her age is {age}.</p>
</form>
);
};
// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<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>
答案 0 :(得分:2)
使用单个useState钩子无法同时设置多个不同的状态。您可以分别设置它们, 例如:
const [userName, setUserName] = useState('');
const [password, setPassword] = useState('');
或将所有状态放入对象,然后使用useState挂钩更新该对象。 来源:https://daveceddia.com/usestate-hook-examples/ 示例:
const [form, setState] = useState({
username: '',
password: ''
});
const updateField = e => {
setState({
...form,
[e.target.name]: e.target.value
});
};
return (
<form onSubmit={printValues}>
<label>
Username:
<input
value={form.username}
name="username"
onChange={updateField}
/>
</label>
<br />
<label>
Password:
<input
value={form.password}
name="password"
type="password"
onChange={updateField}
/>
</label>
<br />
<button>Submit</button>
</form>
);
答案 1 :(得分:0)
您有两种选择可以达到预期的效果。
例如,您可以创建一个函数工厂。
ERROR org.springframework.boot.SpringApplication - Application run failed
cdb-be_1 | java.lang.IllegalStateException: Failed to configure KeyVault property source
cdb-be_1 | at com.microsoft.azure.keyvault.spring.KeyVaultEnvironmentPostProcessorHelper.addKeyVaultPropertySource(KeyVaultEnvironmentPostProcessorHelper.java:80)
cdb-be_1 | at com.microsoft.azure.keyvault.spring.KeyVaultEnvironmentPostProcessor.postProcessEnvironment(KeyVaultEnvironmentPostProcessor.java:26)
cdb-be_1 | at org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEnvironmentPreparedEvent(ConfigFileApplicationListener.java:177)
cdb-be_1 | at org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEvent(ConfigFileApplicationListener.java:165)
cdb-be_1 | at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
cdb-be_1 | at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
cdb-be_1 | at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
cdb-be_1 | at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
cdb-be_1 | at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:76)
cdb-be_1 | at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:53)
cdb-be_1 | at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:342)
cdb-be_1 | at org.springframework.boot.SpringApplication.run(SpringApplication.java:305)
cdb-be_1 | at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
cdb-be_1 | at org.springframework.boot.SpringApplication.run(SpringApplication.java:1204)
cdb-be_1 | at com.siemens.sfs.cdb.be.CdbBackendApplication.main(CdbBackendApplication.java:71)
cdb-be_1 | at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
cdb-be_1 | at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
cdb-be_1 | at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
cdb-be_1 | at java.lang.reflect.Method.invoke(Method.java:498)
cdb-be_1 | at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
cdb-be_1 | at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
cdb-be_1 | at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)
cdb-be_1 | at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52)
cdb-be_1 | Caused by: java.lang.IllegalStateException: Failed to do authentication.
cdb-be_1 | at com.microsoft.azure.keyvault.spring.AzureKeyVaultCredential.refreshToken(AzureKeyVaultCredential.java:66)
cdb-be_1 | at com.microsoft.azure.keyvault.spring.AzureKeyVaultCredential.doAuthenticate(AzureKeyVaultCredential.java:46)
cdb-be_1 | at com.microsoft.azure.keyvault.authentication.KeyVaultCredentials.doAuthenticate(KeyVaultCredentials.java:420)
cdb-be_1 | at com.microsoft.azure.keyvault.authentication.KeyVaultCredentials.getAuthenticationCredentials(KeyVaultCredentials.java:224)
cdb-be_1 | at com.microsoft.azure.keyvault.authentication.KeyVaultCredentials.buildAuthenticatedRequest(KeyVaultCredentials.java:123)
cdb-be_1 | at com.microsoft.azure.keyvault.authentication.KeyVaultCredentials.buildAuthenticatedRequest(KeyVaultCredentials.java:161)
cdb-be_1 | at com.microsoft.azure.keyvault.authentication.KeyVaultCredentials.access$300(KeyVaultCredentials.java:34)
cdb-be_1 | at com.microsoft.azure.keyvault.authentication.KeyVaultCredentials$1.intercept(KeyVaultCredentials.java:76)
cdb-be_1 | at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
cdb-be_1 | at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
cdb-be_1 | at com.microsoft.rest.interceptors.BaseUrlHandler.intercept(BaseUrlHandler.java:43)
cdb-be_1 | at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
cdb-be_1 | at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
cdb-be_1 | at com.microsoft.rest.interceptors.RequestIdHeaderInterceptor.intercept(RequestIdHeaderInterceptor.java:29)
cdb-be_1 | at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
cdb-be_1 | at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
cdb-be_1 | at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:257)
cdb-be_1 | at okhttp3.RealCall.execute(RealCall.java:93)
cdb-be_1 | at retrofit2.OkHttpCall.execute(OkHttpCall.java:186)
cdb-be_1 | at retrofit2.adapter.rxjava.CallExecuteOnSubscribe.call(CallExecuteOnSubscribe.java:40)
cdb-be_1 | at retrofit2.adapter.rxjava.CallExecuteOnSubscribe.call(CallExecuteOnSubscribe.java:24)
cdb-be_1 | at rx.Observable.unsafeSubscribe(Observable.java:10327)
cdb-be_1 | at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
cdb-be_1 | at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
cdb-be_1 | at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
cdb-be_1 | at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
cdb-be_1 | at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
cdb-be_1 | at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
cdb-be_1 | at rx.Observable.subscribe(Observable.java:10423)
cdb-be_1 | at rx.Observable.subscribe(Observable.java:10390)
cdb-be_1 | at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:443)
cdb-be_1 | at rx.observables.BlockingObservable.single(BlockingObservable.java:340)
cdb-be_1 | at com.microsoft.azure.keyvault.implementation.KeyVaultClientBaseImpl.getSecrets(KeyVaultClientBaseImpl.java:3922)
cdb-be_1 | at com.microsoft.azure.keyvault.implementation.KeyVaultClientCustomImpl.listSecrets(KeyVaultClientCustomImpl.java:1170)
cdb-be_1 | at com.microsoft.azure.keyvault.spring.KeyVaultOperation.fillSecretsList(KeyVaultOperation.java:138)
cdb-be_1 | at com.microsoft.azure.keyvault.spring.KeyVaultOperation.<init>(KeyVaultOperation.java:48)
cdb-be_1 | at com.microsoft.azure.keyvault.spring.KeyVaultEnvironmentPostProcessorHelper.addKeyVaultPropertySource(KeyVaultEnvironmentPostProcessorHelper.java:69)
cdb-be_1 | ... 22 common frames omitted
cdb-be_1 | Caused by: java.lang.IllegalStateException: Failed to do authentication.
cdb-be_1 | at com.microsoft.azure.utils.AADAuthUtil.getToken(AADAuthUtil.java:31)
cdb-be_1 | at com.microsoft.azure.keyvault.spring.AzureKeyVaultCredential.refreshToken(AzureKeyVaultCredential.java:57)
cdb-be_1 | ... 58 common frames omitted
cdb-be_1 | Caused by: java.util.concurrent.ExecutionException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
cdb-be_1 | at java.util.concurrent.FutureTask.report(FutureTask.java:122)
cdb-be_1 | at java.util.concurrent.FutureTask.get(FutureTask.java:206)
cdb-be_1 | at com.microsoft.azure.utils.AADAuthUtil.getToken(AADAuthUtil.java:29)
cdb-be_1 | ... 59 common frames omitted
cdb-be_1 | Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
cdb-be_1 | at sun.security.ssl.Alerts.getSSLException(Alerts.java:198)
cdb-be_1 | at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1967)
cdb-be_1 | at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:331)
cdb-be_1 | at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:325)
cdb-be_1 | at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1688)
cdb-be_1 | at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:226)
cdb-be_1 | at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1082)
cdb-be_1 | at sun.security.ssl.Handshaker.process_record(Handshaker.java:1010)
cdb-be_1 | at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1079)
cdb-be_1 | at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1388)
cdb-be_1 | at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1416)
cdb-be_1 | at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1400)
cdb-be_1 | at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
cdb-be_1 | at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
cdb-be_1 | at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1340)
cdb-be_1 | at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1315)
cdb-be_1 | at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:264)
cdb-be_1 | at com.microsoft.aad.adal4j.AdalOAuthRequest.configureHeaderAndExecuteOAuthCall(AdalOAuthRequest.java:145)
cdb-be_1 | at com.microsoft.aad.adal4j.AdalOAuthRequest.send(AdalOAuthRequest.java:83)
cdb-be_1 | at com.microsoft.aad.adal4j.AdalTokenRequest.executeOAuthRequestAndProcessResponse(AdalTokenRequest.java:87)
cdb-be_1 | at com.microsoft.aad.adal4j.AuthenticationContext.acquireTokenCommon(AuthenticationContext.java:930)
cdb-be_1 | at com.microsoft.aad.adal4j.AcquireTokenCallable.execute(AcquireTokenCallable.java:70)
cdb-be_1 | at com.microsoft.aad.adal4j.AcquireTokenCallable.execute(AcquireTokenCallable.java:38)
cdb-be_1 | at com.microsoft.aad.adal4j.AdalCallable.call(AdalCallable.java:47)
cdb-be_1 | at java.util.concurrent.FutureTask.run(FutureTask.java:266)
cdb-be_1 | at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
cdb-be_1 | at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
cdb-be_1 | at java.lang.Thread.run(Thread.java:748)
cdb-be_1 | Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
cdb-be_1 | at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:450)
cdb-be_1 | at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:317)
cdb-be_1 | at sun.security.validator.Validator.validate(Validator.java:262)
cdb-be_1 | at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:330)
cdb-be_1 | at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:237)
cdb-be_1 | at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
cdb-be_1 | at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1670)
cdb-be_1 | ... 23 common frames omitted
cdb-be_1 | Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
cdb-be_1 | at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
cdb-be_1 | at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
cdb-be_1 | at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
cdb-be_1 | at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:445)
cdb-be_1 | ... 29 common frames omitted
const {useState} = React;
const Example = ({title}) => {
const initialState = {
name: 'John',
age: 25
};
const [{name, age}, setFormState] = useState(initialState);
const handleChange = key => e => {
const newValue = e.target.value
setFormState(oldState => ({
...oldState,
[key]: newValue
}));
};
return (
<form onSubmit={e=>e.preventDefault()}>
<input type='text' id='name' name='name' placeholder={name} onChange={handleChange('name')} />
<p>The person's name is {name}.</p>
<br />
<label htmlFor='age'>Age: </label>
<input type='text' id='age' name='age' placeholder={age} onChange={handleChange('age')} />
<p>His/her age is {age}.</p>
</form>
);
};
// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
或者,如果您需要一个具有更大灵活性的函数工厂(例如,如果您试图在其中存储其他状态),则可以使用useReducer()而不是useState(),然后使用调度函数。作为一个未经测试的粗略例子
<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>
最后,有可能 完全按照您的意思进行操作,并具有一个仅使用ref即可更新状态的函数,无论谁调用它。但这不是推荐的方法。