本质上,我试图创建一个复选框UI —我试图传递一个供列表组件使用的切换功能。但是由于某种原因,我可以传播检查但不能取消检查。
这是我的代码:
这是“父母(家庭)”组件:
import React from 'react';
import RecipeDetail from './RecipeDetail';
import RecipeList from './RecipeList';
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
recipes: [],
favorites: [],
currentRecipe: null,
};
this.onRecipeClick = this.onRecipeClick.bind(this);
this.toggleFavorite = this.toggleFavorite.bind(this);
}
componentDidMount() {
fetch(`${API_URL}/v1/recipes`)
.then(res => res.json())
.then(recipes =>
this.setState({
recipes,
})
);
}
onRecipeClick = id => {
fetch(`${API_URL}/v1/recipes/${id}`)
.then(res => res.json())
.then(recipe =>
this.setState({
currentRecipe: recipe,
})
);
};
toggleFavorite = id => {
this.setState(({ favorites, ...state }) => {
const idx = favorites.indexOf(id);
if (idx !== -1) {
return { ...state, favorites: favorites.filter(f => f.id !== id) };
}
return { ...state, favorites: [...favorites, id] };
});
};
// prettier-ignore
render() {
var { recipes, favorites, currentRecipe } = this.state;
return (
<div>
<main className="px4 flex">
<RecipeList
recipes={recipes}
favorites={favorites}
style={{ flex: 3 }}
onClick={this.onRecipeClick}
onFavorited={this.toggleFavorite}
/>
<RecipeDetail
className="ml4"
recipe={currentRecipe}
style={{ flex: 5 }}
/>
</main>
</div>
);
}
}
export default Home;
这是列表组件:
import React from 'react';
import PropTypes from 'prop-types';
// prettier-ignore
const RecipeList = props => (
<div style={props.style}>
<h2 className="h2"> Recipes </h2>
<ul className="list-reset">
{props.recipes.map(recipe => (
<li
className="py2 border-bottom border-bottom-dashed pointer"
key={recipe.id}
onClick={() => props.onClick(recipe.id)}
>
<span
className="mr1"
onClick={e => {
e.stopPropagation();
props.onFavorited(recipe.id);
}}
role="img"
aria-label="favorite"
>
{props.favorites.includes(recipe.id) ? '✅' : ''}
</span>
<span>{recipe.name}</span>
<span>{recipe.category}</span>
</li>
))}
</ul>
</div>
);
RecipeList.propTypes = {
recipes: PropTypes.array,
favorites: PropTypes.array,
onClick: PropTypes.func,
className: PropTypes.string,
style: PropTypes.object,
};
RecipeList.defaultProps = {
recipes: [],
favorites: [],
};
export default RecipeList;
答案 0 :(得分:1)
您正在将食谱ID添加到Error: Cannot enqueue Query after invoking quit.
数组,而不是具有class gDB {
close() {
return new Promise(function(resolve, reject) {
db.end(function(error) {
if ( error ){
reject(new Error(error));
}
// For some reason it is necessary to reestablish this
db = mysql.createConnection({
host: process.env.DBHOST,
user: process.env.DBUSER,
password: process.env.DBPASS,
database: process.env.DBNAME,
ssl: {
ca: fs.readFileSync(__dirname + '/' + process.env.DBCA)
}
});
resolve(true);
});
});
}
getSnapshotIds(gId, uId) {
return new Promise(function(resolve, reject) {
var sql = 'SELECT id AS snapshotId FROM snapshots WHERE gId=' + db.escape(gId) + ' AND uId=' + db.escape(uId) + ' ORDER BY timestamp DESC';
db.query(sql, function (error, results, fields) {
if (error) {
db.destroy();
reject(new Error(error));
} else {
resolve(results);
}
});
});
}
getSnapshotFull(snapshotId) {
return new Promise(function(resolve, reject) {
var sql = 'SELECT s.id AS snapshotId, s.timestamp, s.gId, s.uId, s.clientId FROM snapshots s INNER JOIN controls c ON s.id = c.snapshotId INNER JOIN weathers w ON s.id = w.snapshotId WHERE s.id=' + db.escape(snapshotId);
db.query(sql, function (error, results, fields) {
if (error) {
db.destroy();
reject(new Error(error));
} else {
resolve(results[0]);
}
});
});
}
getTs(snapshotId) {
return new Promise(function(resolve, reject) {
var sql = 'SELECT t.t, st.value FROM snapshots s LEFT JOIN snapshot_t st ON s.id = st.snapshotId INNER JOIN ts t ON st.tId = t.id WHERE s.id=' + db.escape(snapshotId);
db.query(sql, function (error, results, fields) {
if (error) {
db.destroy();
reject(new Error(error));
} else {
resolve(results);
}
});
});
}
属性的对象。
您只需要比较元素本身与在favorites
方法中传入的id
中即可。
id
答案 1 :(得分:0)
if (idx !== -1) {
return { ...state, favorites: favorites.filter(f => f.id !== id) };
}
在这里遍历数组,使用过滤器检查带有f.id
的对象是否与您要添加的id
参数相同。那就好了。但是,在数组上添加新条目时,这是您正在做的事情:
{ ...state, favorites: [...favorites, id] };
您没有添加新对象,仅添加了ID。每当您尝试取消选中它时,它都会失败。
不知道要执行的操作的细节,但是我认为您应该在toggleFavorite
函数中接受整个对象作为参数,然后执行相等性检查。
它看起来像这样:
toggleFavorite = recipe => {
this.setState(({ favorites, ...state }) => {
const idx = favorites.indexOf(recipe.id);
if (idx !== -1) {
return { ...state, favorites: favorites.filter(f => f.id !== recipe.id) };
}
return { ...state, favorites: [...favorites, recipe] };
});
};
// In your list component...
<span
className="mr1"
onClick={e => {
e.stopPropagation();
props.onFavorited(recipe.id);
}}
role="img"
aria-label="favorite"
>
{props.favorites.find((f) => f.id === recipe.id) ? '✅' : ''}
</span>