我有一个简单的用户列表,其中包含来自以下api的一些详细信息:https://gorest.co.in/public-api/users,我想在其中将所选用户添加到收藏夹列表中。我正在使用react-router在页面之间导航。 React可以做到吗?还是我还需要Redux?
我在这里有完整的LIVE EXAMPLE,其中包含用户页面和收藏夹。
以下是用户列表的代码:
import React from "react";
import axios from "axios";
import NavLinks from "./components/navLink";
export default class UserList extends React.Component {
constructor(props) {
super(props);
this.state = {
list: [],
addToFav: false
};
this.list = [];
}
componentDidMount() {
this.getList();
}
/* get users list */
getList = async () => {
const api =
"https://gorest.co.in/public-api/users?_format=json&access-token=3qIi1MDfD-GXqOSwEHHLH73Y3UitdaFKyVm_";
await axios
.get(api)
.then(response => {
this.list = response.data.result;
this.setState({
list: this.list
});
})
.catch(err => {
console.log(err);
});
};
addToFav = () => {
this.setState(
{
addToFav: !this.state.addToFav
},
() => console.log(this.state.addToFav)
);
};
render() {
let style = {
display: "grid",
gridTemplateColumns: "repeat(auto-fill, minmax(250px, 1fr))",
padding: "1rem",
gridGap: "1rem 1rem"
};
return (
<div>
<NavLinks />
<ul style={style}>
{this.state.list.map(user => {
return (
<li key={user.id}>
<div>
<img className="thumb" alt="" src={user._links.avatar.href} />
</div>
<div className="userInfo">
<p>
{user.first_name} {user.last_name}
</p>
</div>
<button onClick={this.addToFav}>Add to Favorites</button>
</li>
);
})}
</ul>
</div>
);
}
}
谢谢!
答案 0 :(得分:1)
我对您的文件做了一些更改-https://github.com/navabi/JustifiedTextView
答案 1 :(得分:1)
这是一个有效的代码框:https://codesandbox.io/s/brave-fire-4kd4p
这种思路几乎遵循@Chris G所提到的。具有保存用户列表和收藏夹列表的顶级状态。然后将它们作为道具传递给各个组件。
App.js
在此处而不是在UserList组件中放置您的API,以防止不必要的重新渲染。
import React, { Component } from "react";
import UserList from "./userList";
import FavoriteList from "./favoriteList";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import axios from "axios";
export default class App extends Component {
state = {
list: [],
favorites: []
};
addFavorite = favorite => {
const { favorites } = this.state;
if (!favorites.some(alreadyFavorite => alreadyFavorite.id == favorite.id)) {
this.setState({
favorites: [...this.state.favorites, favorite]
});
}
};
getList = async () => {
const api =
"https://gorest.co.in/public-api/users?_format=json&access-token=3qIi1MDfD-GXqOSwEHHLH73Y3UitdaFKyVm_";
await axios
.get(api)
.then(response => {
this.setState({
list: response.data.result
});
})
.catch(err => {
console.log(err);
});
};
componentDidMount() {
this.getList();
}
render() {
return (
<Router>
<Switch>
<Route
path="/"
exact
render={() => (
<UserList list={this.state.list} addFavorite={this.addFavorite} />
)}
/>
<Route
path="/favorites"
render={() => <FavoriteList favorites={this.state.favorites} />}
/>
</Switch>
</Router>
);
} }
UserList.js
在单击按钮时调用addFavorite
事件处理程序,以将该项目传递回父状态。
import React from "react";
import NavLinks from "./components/navLink";
export default class UserList extends React.Component {
render() {
let style = {
display: "grid",
gridTemplateColumns: "repeat(auto-fill, minmax(250px, 1fr))",
padding: "1rem",
gridGap: "1rem 1rem"
};
return (
<div>
<NavLinks />
<ul style={style}>
{this.props.list.map(user => {
return (
<li key={user.id}>
<div>
<img className="thumb" alt="" src={user._links.avatar.href} />
</div>
<div className="userInfo">
<p>
{user.first_name} {user.last_name}
</p>
</div>
<button onClick={() => this.props.addFavorite(user)}>
Add to Favorites
</button>
</li>
);
})}
</ul>
</div>
);
}
}
Favorite.js
使用作为道具传入的favorites
数组并对其进行迭代。
import React from "react";
import NavLinks from "./components/navLink";
export default class FavoriteList extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
const { favorites } = this.props;
return (
<div>
<NavLinks />
<ul>
{favorites.map(user => {
return (
<li key={user.id}>
<div>
<img className="thumb" alt="" src={user._links.avatar.href} />
</div>
<div className="userInfo">
<p>
{user.first_name} {user.last_name}
</p>
</div>
</li>
);
})}
</ul>
</div>
);
}
}
答案 2 :(得分:0)
React可以实现吗?还是我还需要Redux?
如果没有redux
,仅使用组件状态就可以解决大多数(如果不是全部)问题。将状态传递给需要它的组件变得越来越困难,您拥有的状态越全局,并且需要更多不同深度的组件来访问和更新它。
在您的情况下,将收藏夹存储在树上方的组件状态中,然后将其传递给使用它的组件可能就足够了。您可以将其直接传递给组件,也可以使用react context使树中深层的组件可以访问它。
一个简单的示例:
const FavoritesContext = React.createContext({favorites: []});
const FavoritesProvider = ({children}) => {
const [favorites, setFavorites] = useState([]);
const add = useCallback(favorite => setFavorites(current => [...current, favorite]), [setFavorites]);
return (
<FavoritesContext.Provider value={{favorites, add}}>
{children}
</FavoritesContext.Provider>
};
您可以这样使用它:
<FavoritesProvider>
<MyApp />
</FavoritesProvider>
然后在应用程序组件中的任意位置:
const MyComponent = () => {
const {favorites, add} = useContext(FavoritesContext);
const [draft, setDraft] = useState('');
const handleChange = event => setDraft(event.target.value);
const handleAdd = () => {
add(draft);
setDraft('');
};
return (
<div>
<ul>
{favorites.map(favorite => <li>{favorite}</li>)}
</ul>
<input value={draft} type="text" onChange={handleChange} />
<button onClick={handleAdd}>Add</button>
</div>
);
}
在这个简单的示例中,收藏夹只是文本,但也可以是对象。它还演示了如何提供用于添加收藏夹的处理程序。您可以实现例如以相同的方式删除收藏夹的处理程序。
保留您的收藏夹是您可能需要处理的另一个主题。您可以使用例如为此,您可以使用localStorage,也可以将其存储在服务器上的数据库中,并在应用首次安装时获取。
答案 3 :(得分:0)
一种方法是使用浏览器的本地存储。
但是这种方式有点昂贵且同步。
只要通过以下方式更改收藏夹项目的状态,就更新列表
localStorage.setItem('users',JSON.stringify(users));
然后通过
查找喜欢的物品localStorage.getItem('users');//You need to parse this by JSON.parse()
在对象列表中维护一个isFavorite
变量。
let users=[{name:"Mr.A",isFavorite:false},{name:"Mr.B",isFavorite:true},...];
在点击收藏按钮this.addToFav
时,进行如下更改
addToFav=user=>{
const {users}=this.state;
this.setState({
users:users.map(userObject=>userObject.id===user.id?
{...userObject,isFavorite:!userObject.isFavorite}:user)
},()=>{saveToLocal(this.state.users)});
}
现在,即使重新加载页面并一直停留到清除存储空间,您也可以访问收藏夹项目。为此,请使用此localStorage.clear()
。
答案 4 :(得分:0)
我做了相应的更改,请尝试
https://codesandbox.io/s/youthful-poincare-7oeh0
关键是您可以按如下所示使用推送状态链接
<Link to={{ pathname: "/favorites", state: { favList: this.props.favList }}} onClick={() => this.forceUpdate()}>
随后在您的收藏夹页面调用下检索状态
this.props.location.state.favList
答案 5 :(得分:0)
我通过使用react上下文对代码进行了一些更改。 我不会为此使用redux,因为我认为这会太过分了。 无论如何,这里是更新的沙箱...
答案 6 :(得分:-1)
首先,我将您的onClick更改为此:
<button onClick={() => this.addToFav(user.id)}>Add to Favorites</button>
这将允许您将ID传递给addToFave函数。 然后,我将添加一个名为faves(数组)的新状态,每当有人单击添加按钮时,我都会将其ID添加到此数组中。当您要显示收藏夹时,这将允许您过滤原始列表。
this.state = {
list: [],
faves: [],
};
}
addToFav = (id) => {
this.setState(prevState => ({
faves: [...prevState.faves, id],
}));
};
当我想使用收藏夹列表而不是普通列表时,我会这样做:
const favesList = [];
this.state.list.map(listItem =>
this.state.faves.find(
faveId => listItem.id === faveId
) && favesList.push(item);
然后我将其传递给faves组件