Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/423.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 未在传递给子组件的函数内更新React全局变量_Javascript_Reactjs - Fatal编程技术网

Javascript 未在传递给子组件的函数内更新React全局变量

Javascript 未在传递给子组件的函数内更新React全局变量,javascript,reactjs,Javascript,Reactjs,我有一个父组件,它有一些来自祖父母组件的道具,我使用一个道具(对象),并将该对象的值作为道具传递给子组件。我还将一个函数传递给子组件,以便从子组件获取更新后的值 ParentComponent.js const ParentComponent = props => { const { record, saveRecord } = props; const editedRecord = {...record} const handleRecordValues

我有一个父组件,它有一些来自祖父母组件的道具,我使用一个道具(对象),并将该对象的值作为道具传递给子组件。我还将一个函数传递给子组件,以便从子组件获取更新后的值

ParentComponent.js

const ParentComponent = props => {

    const { record, saveRecord } = props;

    const editedRecord = {...record}



    const handleRecordValues = (name, value) => {
       editedRecord[name] = value;
    };

...
    const content = <div>
       <ChildComponent name={record.name} value={record.value} setValue={handleRecordValues} />
       <Button onClick={() => saveRecord(editedRecord)} />
    </div>

    return content;
}

const ChildComponent = props => {

    const { name, value, setValue } = props;
    const [input, setInput] = useState(value);

    const handleChange = (e, text) => {
        setInput(text);
        setValue(name, value);
    }


    return <TextField value={input} onChange={handleChange}/>
}

现在editedRecord值已更新,但出现了另一个问题:
当我有多个组件作为子组件时,它只更新我输入的最后一个条目

您的
setValue
/
handleRecordValues
函数更改变量。。。但是React无法知道变量何时变化

要让React知道,您必须在进行更改后调用
saveRecord(editedRecord)
,或者换句话说,您必须调用状态设置函数,以便React知道更改

通常,在React中,如果不更改上下文/状态/道具(对于上下文/状态,这意味着使用适当的React函数进行更改),React将无法知道如何在响应中重新呈现组件。这意味着组件渲染所依赖的任何数据都需要通过这三种机制中的一种进行更改,而不仅仅是通过普通的Javascript,即
a.b=c

编辑:以澄清评论中的一点。创建状态变量时:

const [myState, myStateSetter] = useState('');
myState
没有什么“魔力”;这只是另一个JS变量。Javascript不会让React知道变量何时更改,因此如果您只是这样做:

 myState = 4;
我不知道你这么做了。如果你告诉它它变了,它才知道它变了。。。如果你打电话:

myStateSetter(4);

下面是我如何修改父组件以使所有内容都能与react一起工作。您遇到的主要问题是react需要知道发生了更改,因此我们需要将值设置为state/set state

const ParentComponent = props => {

    const { record, saveRecord } = props;
    const [editedRecord,setEditedRecord] = useState(record);
    useEffect(()=>{
        //This sets the record straight whenever the parent passes a new record.
        //You'd need to make sure the record is referentially stable when it isn't being updated, though
        setEditedRecord(record);
    },[record])

    const handleRecordValues = (name, value) => {
        setEditedRecord(record=>{...record,[name]:value});
    };

...
    const content = <div>
       <ChildComponent name={editedRecord.name} value={editedRecord.value} setValue={handleRecordValues} />
       <Button onClick={() => saveRecord(editedRecord)} />
    </div>

    return content;
}
constparentcomponent=props=>{
const{record,saveRecord}=props;
const[editedRecord,setEditedRecord]=useState(记录);
useffect(()=>{
//每当父级传递一条新记录时,这将直接设置记录。
//不过,您需要确保记录在不更新时是引用稳定的
SetEditeRecord(记录);
}[记录])
常量handleRecordValues=(名称、值)=>{
setEditeRecord(记录=>{…记录,[名称]:值});
};
...
常量内容=
保存记录(EditeRecord)}/>
返回内容;
}

这就是React实现
状态
的原因,在您的情况下,使用
useState
常量,而不是创建
editedRecord
@AdolfoOnrubia,我尝试将setState用于editedRecord。但它仍然没有按预期工作。当您有多个子组件时,每个组件都需要自己的记录。如果您不知道(我之所以这么说是因为您是新来的),您不应该在一篇堆栈溢出文章中尝试问两个问题。相反,你应该接受最能回答你原始问题的答案(如果有),然后为你的新问题创建一个新帖子(带有新的/相关的代码示例)。对不起,我没有跟上你。每次我更新输入值时,都应该调用setValue,对吗?并且应该更新EditeRecord值。然后,当我单击按钮时,将调用saveRecord。这在React中不起作用,因为React不是魔术:它按照Javascript的规则运行,Javascript不会让您神奇地知道变量何时更改。React可以知道更改的唯一方法(与JS中的任何其他代码相同)是调用React状态(或上下文)设置函数,如
useState
生成的函数(或者更改传递给子组件的
props
)。对于任何不影响组件呈现方式的数据,您仍然可以使用普通的旧Javascript。此规则仅适用于组件呈现相关数据(即,当数据更改时希望看到页面更改时)。事实上,您可以将其视为一个规则,您可以使用它来决定“我应该创建一个普通JS变量还是一个状态变量?”:答案是“数据是否影响组件渲染?”的答案。我没有为EditeRecord使用React state setting函数,因为我认为EditeRecord不是组件渲染相关数据。也许我错了?你能看看我的更新吗?很抱歉。我将创建一个新问题。我认为当我只有一个输入子组件时,这将起作用。如果我有多个组件,我只能从最后一个组件获得更新。
const ParentComponent = props => {

    const { record, saveRecord } = props;
    const [editedRecord,setEditedRecord] = useState(record);
    useEffect(()=>{
        //This sets the record straight whenever the parent passes a new record.
        //You'd need to make sure the record is referentially stable when it isn't being updated, though
        setEditedRecord(record);
    },[record])

    const handleRecordValues = (name, value) => {
        setEditedRecord(record=>{...record,[name]:value});
    };

...
    const content = <div>
       <ChildComponent name={editedRecord.name} value={editedRecord.value} setValue={handleRecordValues} />
       <Button onClick={() => saveRecord(editedRecord)} />
    </div>

    return content;
}