![](/img/trans.png)
[英]Issue with Changing state from 1 React Component inside of another React component
[英]I am changing the state of the REACT component from another component but no refresh
我需要一盏灯看看缺少什么? 当我将用户添加到后端时,我正在更改 Users REACT 组件的 state。 用户添加没有问题。 我发送了 User 元素的 state,当“onSubmit:”发生但 Users REACT 组件没有重新加载时,我更改了 state。 这种方法有什么问题?
import { v4 as uuidv4 } from 'uuid';
import React, { useState, useEffect } from 'react';
import { useFormik } from 'formik';
function unique_id() {
return uuidv4()
}
var PlayersBackend='/players';
const validate = values => {
const errors = {};
if (values.firstName === 0 || values.firstName.replace(/^\s+|\s+$/gm, '').length === 0) {
errors.firstName = 'Required';
} else if (values.firstName.length === 0) {
errors.firstName = 'The message must be no empty';
}
if (values.lastName === 0 || values.lastName.replace(/^\s+|\s+$/gm, '').length === 0) {
errors.lastName = 'Required';
} else if (values.lastName.length === 0) {
errors.lastName = 'The message must be no empty';
}
return errors;
};
const addPlayer = async (firstName, lastName) => {
await fetch(PlayersBackend, {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
"Content-Type":"application/json",
},
body: JSON.stringify({ firstName, lastName })
})
};
const AddPlayerForm=(compUsersState) =>{
const formik = useFormik(
{initialValues:{firstName: '',lastName: '',},
validate,
onSubmit: (values,{resetForm}) =>
{ addPlayer(values.firstName,values.lastName).then();
resetForm();
console.log(compUsersState.compUsersState)
compUsersState.compUsersState(p => p+1);
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
name="firstName"
type="text"
onChange={formik.handleChange}
value={formik.values.firstName}
/>
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
name="lastName"
type="text"
onChange={formik.handleChange}
value={formik.values.lastName}
/>
<button type="submit">Add user</button>
</form>
);
};
export const Users = () => {
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [users, setPlayers] = useState([]);
const [,compUsersState] = useState(0);
useEffect(() => {
fetch(PlayersBackend).then(response => response.json()).then((data) => { setIsLoaded(true);setPlayers(data);}, (error) => {setIsLoaded(true);setError(error);})},[])
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
if (typeof (users._embedded) !== 'undefined')
{
return (
<ul>
<AddPlayerForm compUsersState={compUsersState}/>
{users._embedded.players.map(player => (
<li className="d-flex justify-content-start" key={unique_id()}>
{player.firstName} {player.lastName}
</li>
))}
</ul>
);
}
else return (<ul> </ul> )
}
}
这可能是由于 useEffect 它只在加载组件时执行一次,将用户添加到 useEffect 依赖项可能会有所帮助
useEffect(() => {
fetch(PlayersBackend)
.then((response) => response.json())
.then(
(data) => {
setIsLoaded(true);
setPlayers(data);
},
(error) => {
setIsLoaded(true);
setError(error);
}
);
}, [users,users.length]);
更新:看到useEffect
的回答后,让我想到了一个实现刷新的新思路。
在Users
中,
const [refreshCounter, compUsersState] = useState(0);
useEffect(() => {
fetch(PlayersBackend)
.then((response) => response.json())
.then(
(data) => {
setIsLoaded(true);
setPlayers(data);
},
(error) => {
setIsLoaded(true);
setError(error);
}
);
}, [refreshCounter]);
通过将计数器 state 添加到依赖项数组中,您可以确保每次计数器递增时都会触发useEffect
。
我建议将setPlayers
function 传递给<AddPlayerForm>
,并在成功添加玩家后触发 function 将新玩家添加到users
列表中。
在Users
中,
<AddPlayerForm compUsersState={compUsersState} setPlayers={setPlayers} />
在AddPlayerForm
中,
const AddPlayerForm = ({compUsersState, setPlayers}) => {
const formik = useFormik({
initialValues: { firstName: "", lastName: "" },
validate,
onSubmit: (values, { resetForm }) => {
addPlayer(values.firstName, values.lastName).then();
resetForm();
console.log(compUsersState.compUsersState);
compUsersState.compUsersState((p) => p + 1);
const newPlayer = values; // Or change the format
setPlayers((p) => [...p, newPlayer])
},
});
...
我可以看到您正在尝试通过调用compUsersState((p) => p + 1)
来刷新Users
组件,我认为它正在运行。 如果不确定,请使用 React Developer Tool 检查元素并检查 state 是否已成功更改。
但实际问题是users
state 没有得到更新。 所以用户界面看起来和以前一样。
尝试使用forceupdate
类的
const forceUpdate = React.useReducer(bool => !bool)[1];
并致电 state 更新
forceUpdate();
我的最终解决方案是使用 axios。我将 state 作为参数发送<AddPlayerForm useState={[listPlayers, setPlayers]}/>
当我添加一个用户时,我打电话
let temp_listPlayers=[...listPlayers,response.data]
setPlayers(temp_listPlayers);
这是供您参考的完整代码。
import { v4 as uuidv4 } from 'uuid';
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useFormik } from 'formik';
// PlayersBackend must be change in Sync with the value in package.json
// for now is set for the Backend and Frontend will be in the localhost
//. "proxy": "http://localhost:8080", in package.json
var PlayersBackend='/players';
function unique_id() {
return uuidv4()
}
const validate = values => {
const errors = {};
if (values.firstName === 0 || values.firstName.replace(/^\s+|\s+$/gm, '').length === 0) {
errors.firstName = 'Required';
} else if (values.firstName.length === 0) {
errors.firstName = 'The message must be no empty';
}
if (values.lastName === 0 || values.lastName.replace(/^\s+|\s+$/gm, '').length === 0) {
errors.lastName = 'Required';
} else if (values.lastName.length === 0) {
errors.lastName = 'The message must be no empty';
}
return errors;
};
function AddPlayer(firstName,lastName,useState) {
const data = { firstName: firstName, lastName: lastName };
let listPlayers=useState.useState[0];
let setPlayers=useState.useState[1];
axios.post(PlayersBackend, data)
.then(response => {
let temp_listPlayers=[...listPlayers,response.data]
setPlayers(temp_listPlayers);
}).catch(error => {
console.error('Something went wrong!', error);
});
;}
const AddPlayerForm=(useState) =>{
const formik = useFormik(
{initialValues:{firstName: '',lastName: '',},
validate,
onSubmit: (values,{resetForm}) =>
{ AddPlayer(values.firstName,values.lastName,useState);
resetForm();
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
name="firstName"
type="text"
onChange={formik.handleChange}
value={formik.values.firstName}
/>
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
name="lastName"
type="text"
onChange={formik.handleChange}
value={formik.values.lastName}
/>
<button type="submit">Add user</button>
</form>
);
};
export const Users = () => {
const [listPlayers, setPlayers] = useState({});
const getPlayers = () =>
axios.get(PlayersBackend)
.then((response)=> {
const myPlayers=response.data._embedded.players;
setPlayers(myPlayers);
})
useEffect(()=>getPlayers(),[])
if (typeof(listPlayers.length) !== 'undefined') {
return (
<ul>
<AddPlayerForm useState={[listPlayers, setPlayers]}/>
{listPlayers.map(player => (
<li className="d-flex justify-content-start" key={unique_id()}>
{player.firstName} {player.lastName}
</li>
))}
</ul>
);}
return (
<ul> </ul>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.