状态未按要求设置(React、Hooks)
State Not Getting Set As Required (React, Hooks)
我在设置组件状态时遇到问题。请查看以下详细信息
Codesandbox link - https://codesandbox.io/s/goofy-glade-z32zp
这是我的应用程序组件,包含 4 个子组件
import React, { useState } from "react";
import "./App.css";
import RadioType from "./components/Radio/RadioQuestion";
import CheckBox from "./components/Checkbox/CheckBox";
import SelectType from "./components/SelectBox/Selectbox";
import Slider from "./components/Slider/slider";
import data from "./components/jsonData/data.json";
const App = (props) => {
const [values, setValues] = useState();
const setAnswerState = (details) => {
let newState = [];
if (values !== null && values !== undefined)
newState = JSON.parse(JSON.stringify(values));
if (newState === null || newState === undefined) {
newState = [];
newState.push(details);
} else {
if (
newState.filter((x) => x.question_id === details.question_id).length ===
0
)
newState.push(details);
else {
let indexOfFilteredObj = newState.indexOf(
newState.filter((x) => x.question_id === details.question_id)[0]
);
newState[indexOfFilteredObj] = details;
}
}
setValues(JSON.parse(JSON.stringify(newState)));
console.log(values)
};
return (
<div className="App">
{JSON.stringify(values)}
{data.map((v, i) => {
return (
<div key={i}>
{v.question_type === "radio" && (
<RadioType details={v} onChange={setAnswerState} />
)}
{v.question_type === "checkbox" && (
<CheckBox details={v} onChange={setAnswerState} />
)}
{v.question_type === "select" && (
<SelectType details={v} onChange={setAnswerState} />
)}
{v.question_type === "slider" && (
<div style={{ marginLeft: "300px" }}>
<Slider details={v} onChangeState={setAnswerState} />
</div>
)}
</div>
);
})}
</div>
);
};
export default App;
复选框
import React, { useState } from "react";
const CheckBox = (props) => {
const { details, onChange } = props;
const [checkedValues, setCheckedValues] = useState([]);
const setGlobalState = (value) => {
let answer = value;
let stateObj = {
question_id: details.questionId,
answers: answer,
question_type: "checkbox",
};
onChange(stateObj);
};
return (
<div>
<div>{details.question}</div>
<label>
{details.answers === undefined
? null
: details.answers.map((checkBoxAnswers, index) => {
return (
<div key={index}>
<input
type="checkbox"
name={`checkbox_${details.questionId}`}
value={checkBoxAnswers}
onChange={(e) => {
let currentValues = checkedValues;
if (e.target.checked) currentValues.push(e.target.value);
else {
const index = currentValues.indexOf(e.target.value);
if (index > -1) {
currentValues.splice(index, 1);
}
}
setCheckedValues(currentValues);
setGlobalState(currentValues);
}}
/>
<label key={index}>{checkBoxAnswers}</label>
</div>
);
})}
</label>
<br />
</div>
);
};
export default CheckBox;
电台
import React from "react";
const RadioType = (props) => {
const { details, onChange } = props;
const setGlobalState = (value) => {
let answer = [value];
let stateObj = {
question_id: details.questionId,
answers: answer,
question_type: "radio",
};
onChange(stateObj);
};
return (
<div>
<div>{details.question}</div>
<label>
{details.answers === undefined
? null
: details.answers.map((radioQuestionAnswers, index) => {
return (
<div key={index}>
<input
type="radio"
name={`radio_${details.questionId}`}
value={radioQuestionAnswers}
onChange={(e) => setGlobalState(e.target.value)}
/>
<label key={index}>{radioQuestionAnswers}</label>
</div>
);
})}
</label>
<br />
</div>
);
};
export default RadioType;
Select
import React from "react";
const SelectType = (props) => {
const { details, onChange } = props;
const setGlobalState = (value) => {
let answer = [value];
let stateObj = {
question_id: details.questionId,
answers: answer,
question_type: "select",
};
onChange(stateObj);
};
return (
<>
<div>{details.question}</div>
<select
name={`checkbox_${details.questionId}`}
onChange={(e) => {
setGlobalState(e.target.value);
}}
>
{details.answers === undefined
? null
: props.details.answers.map((selectAns, index) => {
return (
<option key={index} value={selectAns}>
{selectAns}
</option>
);
})}
</select>
</>
);
};
export default SelectType;
NouiSlider
import React from "react";
import Nouislider from "nouislider-react";
import "nouislider/distribute/nouislider.css";
const Slider = (props) => {
const { details, onChangeState } = props;
const setGlobalState = (value) => {
let answer = [value];
let stateObj = {
question_id: details.questionId,
answers: answer,
question_type: "slider",
};
onChangeState(stateObj);
};
return (
<>
<Nouislider
style={{ color: "red", width: "600px" }}
start={[0]}
pips={{ mode: "count", values: details.division }}
clickablePips
range={{
min: details.range.min,
max: details.range.max,
}}
onChange={(e) => {
let valueOfSlider = parseFloat(e[0]);
setGlobalState(valueOfSlider);
}}
/>
</>
);
};
export default Slider;
每当我尝试从单选复选框或 select 设置状态时都会遇到问题,它确实设置了状态并通过作为 prop 传递给子项的 setAnswerState 方法正确更新。每当我尝试更改滑块时,setAnswerState 获取的值为 undefined 或 null,因此其他子组件设置的完整状态丢失,我无法找到状态丢失背后的原因。
这里是我用来测试的样本数据
[
{
"question": "When was the Cilivar War?",
"question_type": "radio",
"answers": ["1877-1866", "1877-1872", "1877-1851", "1877-1880"],
"questionId": "099011"
},
{
"question": "World's Largest country by population?",
"answers": ["China", "Canada", "United kingdom", "India"],
"correctAns": "China",
"question_type": "checkbox",
"dependent_question_id": [
{
"question_id": "099011",
"answers_to_match": [
{
"operator": "AND",
"answers": ["1877-1866"]
}
]
}
],
"questionId": "0990758"
},
{
"question": "Where is the Tajmahal?",
"answers": ["Agra", "Mumbai", "Pune", "Punjab"],
"correctAns": "Agra",
"question_type": "select",
"dependent_question_id": [
{
"question_id": "099011",
"answers_to_match": [
{
"operator": "AND",
"answers": ["1877-1866"]
}
]
},
{
"question_id": "099078",
"answers_to_match": [
{
"operator": "AND",
"answers": ["Canada", "United kingdom"]
}
]
}
],
"questionId": "099096"
},
{
"questionId": "0002346",
"question_type": "slider",
"division": 5,
"range":
{
"min": 0,
"max": 100
}
}
]
只需在useState()
中添加[]
,如下图:
const [values, setValues] = useState([]);
然后将setAnswerState
方法更新为:
const setAnswerState = (details) => {
// below statement will handle both the cases:
// updating an existing question as well as adding in a new question
setValues((prevValues) => [
...prevValues.filter((x) => x.question_id !== details.question_id),
{ ...details }
]);
};
在你的应用组件中,你需要在 useState() 中添加 [] as
const [values, setValues] = useState([]);
在 setAnswerState() 内部,使用 newState 作为 setValues() 的值。
setValues(newState)
没有
setValues(JSON.parse(JSON.stringify(newState)));
我在设置组件状态时遇到问题。请查看以下详细信息
Codesandbox link - https://codesandbox.io/s/goofy-glade-z32zp
这是我的应用程序组件,包含 4 个子组件
import React, { useState } from "react";
import "./App.css";
import RadioType from "./components/Radio/RadioQuestion";
import CheckBox from "./components/Checkbox/CheckBox";
import SelectType from "./components/SelectBox/Selectbox";
import Slider from "./components/Slider/slider";
import data from "./components/jsonData/data.json";
const App = (props) => {
const [values, setValues] = useState();
const setAnswerState = (details) => {
let newState = [];
if (values !== null && values !== undefined)
newState = JSON.parse(JSON.stringify(values));
if (newState === null || newState === undefined) {
newState = [];
newState.push(details);
} else {
if (
newState.filter((x) => x.question_id === details.question_id).length ===
0
)
newState.push(details);
else {
let indexOfFilteredObj = newState.indexOf(
newState.filter((x) => x.question_id === details.question_id)[0]
);
newState[indexOfFilteredObj] = details;
}
}
setValues(JSON.parse(JSON.stringify(newState)));
console.log(values)
};
return (
<div className="App">
{JSON.stringify(values)}
{data.map((v, i) => {
return (
<div key={i}>
{v.question_type === "radio" && (
<RadioType details={v} onChange={setAnswerState} />
)}
{v.question_type === "checkbox" && (
<CheckBox details={v} onChange={setAnswerState} />
)}
{v.question_type === "select" && (
<SelectType details={v} onChange={setAnswerState} />
)}
{v.question_type === "slider" && (
<div style={{ marginLeft: "300px" }}>
<Slider details={v} onChangeState={setAnswerState} />
</div>
)}
</div>
);
})}
</div>
);
};
export default App;
复选框
import React, { useState } from "react";
const CheckBox = (props) => {
const { details, onChange } = props;
const [checkedValues, setCheckedValues] = useState([]);
const setGlobalState = (value) => {
let answer = value;
let stateObj = {
question_id: details.questionId,
answers: answer,
question_type: "checkbox",
};
onChange(stateObj);
};
return (
<div>
<div>{details.question}</div>
<label>
{details.answers === undefined
? null
: details.answers.map((checkBoxAnswers, index) => {
return (
<div key={index}>
<input
type="checkbox"
name={`checkbox_${details.questionId}`}
value={checkBoxAnswers}
onChange={(e) => {
let currentValues = checkedValues;
if (e.target.checked) currentValues.push(e.target.value);
else {
const index = currentValues.indexOf(e.target.value);
if (index > -1) {
currentValues.splice(index, 1);
}
}
setCheckedValues(currentValues);
setGlobalState(currentValues);
}}
/>
<label key={index}>{checkBoxAnswers}</label>
</div>
);
})}
</label>
<br />
</div>
);
};
export default CheckBox;
电台
import React from "react";
const RadioType = (props) => {
const { details, onChange } = props;
const setGlobalState = (value) => {
let answer = [value];
let stateObj = {
question_id: details.questionId,
answers: answer,
question_type: "radio",
};
onChange(stateObj);
};
return (
<div>
<div>{details.question}</div>
<label>
{details.answers === undefined
? null
: details.answers.map((radioQuestionAnswers, index) => {
return (
<div key={index}>
<input
type="radio"
name={`radio_${details.questionId}`}
value={radioQuestionAnswers}
onChange={(e) => setGlobalState(e.target.value)}
/>
<label key={index}>{radioQuestionAnswers}</label>
</div>
);
})}
</label>
<br />
</div>
);
};
export default RadioType;
Select
import React from "react";
const SelectType = (props) => {
const { details, onChange } = props;
const setGlobalState = (value) => {
let answer = [value];
let stateObj = {
question_id: details.questionId,
answers: answer,
question_type: "select",
};
onChange(stateObj);
};
return (
<>
<div>{details.question}</div>
<select
name={`checkbox_${details.questionId}`}
onChange={(e) => {
setGlobalState(e.target.value);
}}
>
{details.answers === undefined
? null
: props.details.answers.map((selectAns, index) => {
return (
<option key={index} value={selectAns}>
{selectAns}
</option>
);
})}
</select>
</>
);
};
export default SelectType;
NouiSlider
import React from "react";
import Nouislider from "nouislider-react";
import "nouislider/distribute/nouislider.css";
const Slider = (props) => {
const { details, onChangeState } = props;
const setGlobalState = (value) => {
let answer = [value];
let stateObj = {
question_id: details.questionId,
answers: answer,
question_type: "slider",
};
onChangeState(stateObj);
};
return (
<>
<Nouislider
style={{ color: "red", width: "600px" }}
start={[0]}
pips={{ mode: "count", values: details.division }}
clickablePips
range={{
min: details.range.min,
max: details.range.max,
}}
onChange={(e) => {
let valueOfSlider = parseFloat(e[0]);
setGlobalState(valueOfSlider);
}}
/>
</>
);
};
export default Slider;
每当我尝试从单选复选框或 select 设置状态时都会遇到问题,它确实设置了状态并通过作为 prop 传递给子项的 setAnswerState 方法正确更新。每当我尝试更改滑块时,setAnswerState 获取的值为 undefined 或 null,因此其他子组件设置的完整状态丢失,我无法找到状态丢失背后的原因。
这里是我用来测试的样本数据
[
{
"question": "When was the Cilivar War?",
"question_type": "radio",
"answers": ["1877-1866", "1877-1872", "1877-1851", "1877-1880"],
"questionId": "099011"
},
{
"question": "World's Largest country by population?",
"answers": ["China", "Canada", "United kingdom", "India"],
"correctAns": "China",
"question_type": "checkbox",
"dependent_question_id": [
{
"question_id": "099011",
"answers_to_match": [
{
"operator": "AND",
"answers": ["1877-1866"]
}
]
}
],
"questionId": "0990758"
},
{
"question": "Where is the Tajmahal?",
"answers": ["Agra", "Mumbai", "Pune", "Punjab"],
"correctAns": "Agra",
"question_type": "select",
"dependent_question_id": [
{
"question_id": "099011",
"answers_to_match": [
{
"operator": "AND",
"answers": ["1877-1866"]
}
]
},
{
"question_id": "099078",
"answers_to_match": [
{
"operator": "AND",
"answers": ["Canada", "United kingdom"]
}
]
}
],
"questionId": "099096"
},
{
"questionId": "0002346",
"question_type": "slider",
"division": 5,
"range":
{
"min": 0,
"max": 100
}
}
]
只需在useState()
中添加[]
,如下图:
const [values, setValues] = useState([]);
然后将setAnswerState
方法更新为:
const setAnswerState = (details) => {
// below statement will handle both the cases:
// updating an existing question as well as adding in a new question
setValues((prevValues) => [
...prevValues.filter((x) => x.question_id !== details.question_id),
{ ...details }
]);
};
在你的应用组件中,你需要在 useState() 中添加 [] as
const [values, setValues] = useState([]);
在 setAnswerState() 内部,使用 newState 作为 setValues() 的值。
setValues(newState)
没有
setValues(JSON.parse(JSON.stringify(newState)));