Javascript 函数内部的状态始终相同/初始
从对象调用remove()函数。如何在remove()函数中获取更新的状态值Javascript 函数内部的状态始终相同/初始,javascript,reactjs,react-hooks,javascript-objects,Javascript,Reactjs,React Hooks,Javascript Objects,从对象调用remove()函数。如何在remove()函数中获取更新的状态值 const [InfoBoxPin, setInfoBoxPin] = useState([]) const createInfoBoxPin = (descriptions) =>{ var newPin = { "location":currentLoc, "addHand
const [InfoBoxPin, setInfoBoxPin] = useState([])
const createInfoBoxPin = (descriptions) =>{
var newPin = {
"location":currentLoc,
"addHandler":"mouseover",
"infoboxOption": {
title: 'Comment',
description: "No comment Added",
actions: [{
label:'Remove Pin',
eventHandler: function () {
remove(newPin.location) //FUNCTION CALLED HERE
}
}] }
}
setInfoBoxPin((InfoBoxPin)=>[...InfoBoxPin, newPin ]) // UPDATE STATE. Push the above object.
}
const remove = (pos) =>{
console.log(InfoBoxPin) //NEVER GETTING UPDATED STATE HERE.
//Other codes here......
}
这是bing地图信息卡。Eventhandler创建了一个可以调用任何函数的按钮。问题在于,您在
删除
函数中引用了旧的状态信息
const [InfoBoxPin, setInfoBoxPin] = useState([])
const createInfoBoxPin = (descriptions) =>{
var newPin = {
"location":currentLoc,
"addHandler":"mouseover",
"infoboxOption": {
title: 'Comment',
description: "No comment Added",
actions: [{
label:'Remove Pin',
eventHandler: function () {
remove(newPin.location) //FUNCTION CALLED HERE
}
}] }
}
setInfoBoxPin((InfoBoxPin)=>[...InfoBoxPin, newPin ]) // UPDATE STATE. Push the above object.
}
const remove = (pos) =>{
console.log(InfoBoxPin) //NEVER GETTING UPDATED STATE HERE.
//Other codes here......
}
当您调用setInfoBoxPin
时,InfoBoxPin
的状态将注册,以便在下次呈现UI时进行更新。这意味着在当前状态下,它将是相同的(空),并且指向它的所有链接都将引用空数组
为了解决这个问题,您必须将新状态从视图本身传递给相应的函数
示例#1
在这里,我为您创建了一个CodeSandBox:
下面是从中截取的代码:
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [state, setState] = useState({
InfoBoxPin: [],
output: []
});
const createInfoBoxPin = (descriptions) => {
var newPin = {
location: Math.round(Math.random(10) * 1000),
addHandler: "mouseover",
infoboxOption: {
title: "Comment",
description: "No comment Added",
actions: [
{
label: "Remove Pin",
eventHandler: removePin
},
{
label: "Update Pin",
eventHandler: updatePin
}
]
}
};
setState({ ...state, InfoBoxPin: [...state.InfoBoxPin, newPin] });
};
const updatePin = (key, state) => {
var text = `Updating pin with key #${key} - ${state.InfoBoxPin[key].location}`;
setState({ ...state, output: [...state.output, text] });
console.log(text, state.InfoBoxPin);
};
const removePin = (key, state) => {
var text = `Removing pin with key #${key} - ${state.InfoBoxPin[key].location}`;
setState({ ...state, output: [...state.output, text] });
console.log(text, state.InfoBoxPin);
};
return (
<div className="App">
<h1>React setState Example</h1>
<h2>Click on a button to add new Pin</h2>
<button onClick={createInfoBoxPin}>Add new Pin</button>
<div>----</div>
{state.InfoBoxPin.map((pin, pin_key) => {
return (
<div key={pin_key}>
<span>Pin: {pin.location} </span>
{pin.infoboxOption.actions.map((action, action_key) => {
return (
<button
key={action_key}
onClick={() => action.eventHandler(pin_key, state)}
>
{action.label}
</button>
);
})}
</div>
);
})}
<h4> OUTPUT </h4>
<ul style={{ textAlign: "left" }}>
{state.output.map((txt, i) => {
return <li key={i}>{txt}</li>;
})}
</ul>
</div>
);
}
示例#3(ES6)未访问创建的元素
这个例子将展示如何使用我们自己的参数和来自自动生成HTML元素事件的状态数据处理来自第三方库的回调
代码沙盒链接:
代码段:
import React from "react";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
InfoBoxPin: [],
pinName: ""
};
/* ------------ method #1 using .bind(this) ------------ */
this.setPinName = this.setPinName.bind(this);
}
remove(key) {
this.state.InfoBoxPin.splice(key, 1);
this.setState({ InfoBoxPin: this.state.InfoBoxPin });
}
add(pinName) {
this.state.InfoBoxPin.push(pinName);
this.setState({ InfoBoxPin: this.state.InfoBoxPin });
}
processPinNameAndAdd() {
let pinName = this.state.pinName.trim();
if (pinName === "") pinName = Math.round(Math.random() * 1000);
this.add(pinName);
}
setPinName(event) {
this.setState({ pinName: event.target.value });
}
render() {
return (
<div className="shopping-list">
<h1>Pin List</h1>
<p>Hit "Add New Pin" button.</p>
<p>(Optional) Provide your own name for the pin</p>
<input
onInput={this.setPinName}
value={this.state.pinName}
placeholder="Custom name"
></input>
{/* ------------ method #2 using .call(this) ------------ */}
<button onClick={() => this.processPinNameAndAdd.call(this)}>
Add new Pin
</button>
<ul>
{this.state.InfoBoxPin.map((pin, pinKey) => {
return (
<li key={pinKey}>
<div>pin: {pin}</div>
{/* ------------ method #3 using .apply(this, [args]) ------------ */}
<button onClick={() => this.remove.apply(this, [pinKey])}>
Delete Pin
</button>
</li>
);
})}
</ul>
</div>
);
}
}
export default App;
import React from "react";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
InfoBoxPin: [],
lastPinId: 0,
pinName: ""
};
this.setPinName = this.setPinName.bind(this);
}
remove(id) {
let keyToRemove = null;
this.state.InfoBoxPin.forEach((pin, key) => {
if (pin.id === id) keyToRemove = key;
});
this.state.InfoBoxPin.splice(keyToRemove, 1);
this.setState({ InfoBoxPin: this.state.InfoBoxPin });
}
add(data, id) {
this.state.InfoBoxPin.push({ id: id, data: data });
this.setState({
InfoBoxPin: this.state.InfoBoxPin,
lastPinId: id
});
}
processPinNameAndAdd() {
let pinName = this.state.pinName.trim();
if (pinName === "") pinName = Math.round(Math.random() * 1000);
var newPinId = this.state.lastPinId + 1;
var newPin = {
location: pinName,
addHandler: "mouseover",
infoboxOption: {
title: "Comment",
description: "No comment Added",
actions: [
{
label: "Remove Pin #" + newPinId,
// [ES6 class only] using () => func() for callback function
// By doing so we don't need to use bind,call,apply to pass class ref [this] to a function.
eventHandler: () => this.remove(newPinId)
}
]
}
};
this.add(newPin, newPinId);
}
setPinName(event) {
this.setState({ pinName: event.target.value });
}
render() {
return (
<div className="shopping-list">
<h1>Pin List</h1>
<p>Hit "Add New Pin" button.</p>
<p>(Optional) Provide your own name for the pin</p>
<input onInput={this.setPinName} value={this.state.pinName}></input>
{/*
[ES6 class only] Using {() => func()} for event handler.
By doing so we don't need to use func.bind(this) for passing class ref at constructor
*/}
<button onClick={() => this.processPinNameAndAdd()}>Add new Pin</button>
<ul>
{this.state.InfoBoxPin.map((pin, pKey) => {
return (
<li key={pKey}>
<div>pin: {pin.data.location}</div>
{pin.data.infoboxOption.actions.map((action, aKey) => {
return (
<button key={aKey} onClick={action.eventHandler}>
{action.label}
</button>
);
})}
</li>
);
})}
</ul>
</div>
);
}
}
export default App;
请注意,使用arrow函数
()=>func
将类ref传递给remove
函数非常重要。感谢您的努力,但您不能更改newPin对象的结构,因为Bing map将以这种格式接收它。事件处理程序键在Bing地图上生成一个可单击的按钮。因此,您必须维护它们提供的结构,eventHandler:function(){}。我们必须为事件处理程序分配一个函数。我们不能在那里打字。有什么想法吗?我已经更新了我的答案和代码沙盒示例。你可以去看看。希望这将对您有所帮助。添加了另一个使用类的示例。这创造了一个机会,可以使用一些不同的方法来检索应用程序状态。非常感谢。我会尝试你的方法。我尝试了你的方法,但我的“关键”是获取指针事件。你遇到了JavaScript中称为“陈旧闭包”的问题,它不是特定的反应,但在引用状态时很容易在react中命中。。。
const [InfoBoxPin, setInfoBoxPin] = useState([])
const createInfoBoxPin = (descriptions) =>{
var newPin = {
"location":currentLoc,
"addHandler":"mouseover",
"infoboxOption": {
title: 'Comment',
description: "No comment Added",
actions: [{
label:'Remove Pin',
eventHandler: function () {
remove(newPin.location) //FUNCTION CALLED HERE
}
}] }
}
setInfoBoxPin((InfoBoxPin)=>[...InfoBoxPin, newPin ]) // UPDATE STATE. Push the above object.
}
const remove = (pos) =>{
console.log(InfoBoxPin) //NEVER GETTING UPDATED STATE HERE.
//Other codes here......
}