Javascript React Hooks:设置组件状态而不重新渲染两次
所以我有两个组件:一个输入组件,它基本上只是一个按钮,将输入值的当前状态设置为活动状态,然后将值对象发送给其父组件:Javascript React Hooks:设置组件状态而不重新渲染两次,javascript,reactjs,Javascript,Reactjs,所以我有两个组件:一个输入组件,它基本上只是一个按钮,将输入值的当前状态设置为活动状态,然后将值对象发送给其父组件: import React, { useState, useEffect } from 'react'; import './Input.css'; const Input = (props) => { // input state: const title = props.title; const index = props.index;
import React, { useState, useEffect } from 'react';
import './Input.css';
const Input = (props) => {
// input state:
const title = props.title;
const index = props.index;
const [active, setActive] = useState(false);
const [inputValue, setInputValue] = useState({index, title, active});
// sets active status based on what status is in Question component
// the logic there would only allow 1 radio input to be active as opposed to checkboxes where we have multiple active
useEffect(() => {
setActive(props.active);
}, [props.active]);
// stores activity status of single input and re-runs only when 'active' changes (when clicking the button)
useEffect(() => {
setInputValue({index, title, active});
}, [active]);
// returns updated input value to Question component
useEffect(() => {
return props.selected(inputValue);
}, [inputValue]);
return (
<div className='input'>
<button
data-key={title}
className={props.active ? 'highlight' : ''}
onClick={() => setActive(active => !active)}
>
{title}
</button>
</div>
);
}
export default Input;
问题检查从另一个父组件接收的当前问题类型是否为“单选”按钮类型,在这种情况下,您只能有一个选项。因此,目前我将其设置为:
import React, { useState, useEffect } from 'react';
import s from './Question.css';
import Input from './Input/Input';
const Question = (props) => {
// create intitial state of options
let initialState = [];
for (let i=0; i < props.options.length; i++) {
initialState.push(
{
index: i,
option: props.options[i],
active: false,
}
)
}
// question state:
let questionIndex = props.index;
let questionActive = props.active;
let questionTitle = props.question;
let questionType = props.type;
let [questionValue, setQuestionValue] = useState(initialState);
let [isAnswered, setIsAnswered] = useState(false);
useEffect(() => {
console.log(questionValue);
}, [questionValue]);
// stores currently selected input value for question and handles logic according to type
const storeInputValue = (inputValue) => {
let questionInputs = [...questionValue];
let index = inputValue.index;
// first set every input value to false when type is radio, with the radio-type you can only choose one option
if (questionType === 'radio') {
for (let i=0; i < questionInputs.length; i++) {
questionInputs[i].active = false;
}
}
questionInputs[index].active = inputValue.active;
setQuestionValue([...questionInputs]);
// set state that checks if question has been answered
questionValue.filter(x => x.active).length > 0 ? setIsAnswered(true) : setIsAnswered(false);
}
// creates the correct input type choices for the question
let inputs = [];
for (const [index, input] of props.options.entries()) {
inputs.push(
<Input
key={index}
index={index}
title={input}
active={questionValue[index].active}
selected={storeInputValue}
/>
);
}
// passes current state (selected value) and the index of question to parent (App.js) component
const saveQuestionValue = (e) => {
e.preventDefault();
props.selection(questionValue, questionIndex, questionTitle);
}
return (
<div className={`question ${!questionActive ? 'hide' : ''}`}>
<h1>{props.question}</h1>
<div className="inputs">
{inputs}
</div>
<a className={`selectionButton ${isAnswered ? 'highlight' : ''}`} href="" onClick={e => saveQuestionValue(e)}>
<div>Save and continue -></div>
</a>
</div>
);
}
export default Question;
使用此设置,当我单击输入时,它会将其发送到问题组件,该组件会将prop.active返回到输入,以便突出显示输入值。但当我单击一个新输入时,它会重新呈现两次,因为它会侦听输入中的活动状态变化,并将所有输入设置为false
我的问题是:如何设置此代码中的逻辑,使其像无线电输入一样,只将当前选定的输入设置为活动,而不是首先将每个输入设置为活动=假?您不应该在两个不同的组件中复制状态值。对于一个价值的状态,应该只有一个单一的真理来源。这是最重要的反应模式之一,甚至在中提到过 相反,你应该让它生活在最接近的共同祖先。您的组件不应该有任何内部状态-它们应该是纯函数,除了呈现当前值并提供回调来更新所述值之外,什么都不做。但是,他们自己并不存储该值,而是将其作为道具传递给他们
激活输入的所有逻辑及其值都应该存在于父组件中,并从父组件传递下来。无论何时在子组件中设置状态,然后以某种方式将该状态传递回父组件都是一个警告标志,因为在React.中,不应在两个不同组件中重复状态值。对于一个价值的状态,应该只有一个单一的真理来源。这是最重要的反应模式之一,甚至在中提到过 相反,你应该让它生活在最接近的共同祖先。您的组件不应该有任何内部状态-它们应该是纯函数,除了呈现当前值并提供回调来更新所述值之外,什么都不做。但是,他们自己并不存储该值,而是将其作为道具传递给他们
激活输入的所有逻辑及其值都应该存在于父组件中,并从父组件传递下来。无论何时在子组件中设置状态,然后以某种方式将该状态传递回父组件都是一个警告标志,因为在React中。感谢您的解释。我将根据此逻辑重新生成代码,然后重试!我已经尝试过使用它,现在可以使用了,非常感谢您的帮助!对于任何与此问题斗争的人:我在中所做的是使用当前输入的索引执行回调onClick函数,在中,我将当前选择的输入设置为true,以便突出显示正确的输入。@mitKiliç很高兴我能提供帮助。请投票并接受我的回答,表明你的问题已经解决谢谢你的解释。我将根据此逻辑重新生成代码,然后重试!我已经尝试过使用它,现在可以使用了,非常感谢您的帮助!对于任何与此问题斗争的人:我在中所做的是使用当前输入的索引执行回调onClick函数,在中,我将当前选择的输入设置为true,以便突出显示正确的输入。@mitKiliç很高兴我能提供帮助。请投票并接受我的回答,表明你的问题已经解决