Why is this.props.username undefined in React-Redux? - reactjs

When I try to access this.props.username in:
loginClick = (event) => {
event.preventDefault();
console.log('Login submit click, props.username: ' + this.props.username);
this.props.loginDispatch(this.props.username);
}
I get undefined.
Can you tell me what I'm missing?
Reducer:
import { fromJS } from 'immutable';
import { DEFAULT_ACTION, SET_USERNAME } from './constants';
const initialStateMutable = {
username: ''
};
const initialState = fromJS(initialStateMutable);
function loginReducer(state = initialState, action) {
switch (action.type) {
case DEFAULT_ACTION:
return state;
case SET_USERNAME:
console.log('reducer state.username value: ' + state.username);
return {
...state,
username: action.username
};
default:
return state;
}
}
Action:
import { LOGIN_SUBMIT, SET_USERNAME } from './constants';
export const loginDispatch = (name) => ({
type: LOGIN_SUBMIT,
name,
});
export const setUsername = (username) => {
return {
type: SET_USERNAME,
username,
};
};
Selector:
import { createSelector } from 'reselect';
const selectLoginPageDomain = () => (state) => state.get('loginPage');
const makeSelectLoginPage = () => createSelector(
selectLoginPageDomain(),
(substate) => substate.toJS()
);
export default makeSelectLoginPage;
export {
selectLoginPageDomain,
};
index.tsx:
import makeSelectLoginPage from './selector';
import * as React from 'react';
import { loginDispatch, setUsername } from './actions';
import { connect } from 'react-redux';
interface ILoginProps {
loginDispatch: Function;
setUsername: Function;
username: string;
}
interface ILoginState {
}
class LoginPage extends React.Component<ILoginProps, ILoginState> {
constructor(props, context) {
super(props, context);
}
updateInputValue = (event) => {
event.preventDefault();
console.log('Current value of props.username: ' + this.props.username);
this.props.setUsername(event.target.value);
}
loginClick = (event) => {
event.preventDefault();
console.log('Login submit click, props.username: ' + this.props.username);
this.props.loginDispatch(this.props.username);
}
render() {
return (
<div>
<div className="row">
<div className="col-xs-12">
<div className="card">
<div className="card-inside">
<div className="alignc">
<form onSubmit={this.loginClick} className="row">
<div>
<div className="alignl">
Enter username for calculation history.
</div>
<div>
<input type="text" value={this.props.username} onChange={this.updateInputValue}/>
</div>
<button type="submit" value="Submit">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
const mapStateToProps = (state) => ({
...state,
username: state.username,
...makeSelectLoginPage()(state),
});
const mapDispatchToProps = (dispatch) => ({
dispatch,
setUsername: (value: string) => dispatch(setUsername(value)),
loginDispatch: (name: string) => dispatch(loginDispatch(name)),
});
export default connect(mapStateToProps, mapDispatchToProps)(LoginPage);
UPDATE:
I just realized I'm getting this error from the selector:
Uncaught TypeError: substate.toJS is not a function
at eval (eval at ./app/containers/Login/selector.ts

state is an immutable variable. Try this :
const mapStateToProps = (state) => ({
...state.toJS(),
username: state.get('username'),
...makeSelectLoginPage()(state),
});

Related

TypeError: dispatch is not a function React button

Hi im new to react and i just cant understand why this is not working.
this is my product.js file that im trying to change state when i click on the button "addToBasket"
import React from "react";
import "./Product.css";
import { useStateValue } from "./StateProvider";
function Product({ id, title, image, price, rating }) {
const { dispatch } = useStateValue();
const addToBasket = () => {
dispatch({
type: "ADD_TO_BASKET",
item: {
id: id,
title: title,
image: image,
price: price,
rating: rating,
},
});
};
return (
<div className="product">
<div className="product__info">
<p>{title}</p>
<p className="product__price">
<small>$</small>
<strong>{price}</strong>
</p>
<div className="product__rating">
{Array(rating)
.fill()
.map((_) => (
<p>⭐</p>
))}
</div>
</div>
<img src={image} alt="" />
<button onClick={addToBasket}>Add to basket</button>
</div>
);
}
export default Product;
so i can change one of these states.
i have all the dependencies i need, double checked. Cant understand if its my mistake or some bug
export const initialState = {
basket: [],
user: null,
};
export const getBasketTotal = (basket) =>
basket?.reduce((amount, item) => item.price + amount, 0);
const reducer = (state, action) => {
console.log(action);
switch (action.type) {
case "SET_USER":
return {
...state,
user: action.user,
};
case "ADD_TO_BASKET":
return {
...state,
basket: [...state.basket, action.item],
};
case "REMOVE_FROM_BASKET":
let newBasket = [...state.basket];
const index = state.baslet.findIndex(
(basketItem) => basketItem.id === action.id
);
if (index >= 0) {
newBasket.splice(index, 1);
} else {
}
return { ...state, basket: newBasket };
default:
return state;
}
};
export default reducer;
edit: This is my StateProvider.js
import React, { createContext, useContext, useReducer } from "react";
export const StateContext = createContext();
export const StateProvider = ({ reducer, initialState, children }) => (
<StateContext.Provider value={useReducer(reducer, initialState)}>
{children}
</StateContext.Provider>
);
export const useStateValue = () => useContext(StateContext);

How to access to set redux props to react state?

This is my code and I try to set email of user to state and set it with other data:
import React, {Component} from "react";
import PropTypes from "prop-types";
import * as actionCreators from '../../actions/authAction';
import {loadUser, setPass , register} from "../../actions/authAction";
import {connect} from "react-redux";
import { bindActionCreators } from "redux";
import {clearError} from "../../actions/errorAction";
import {toast} from "react-toastify";
import store from "../../store";
class RegisterFinal extends Component {
componentDidMount() {
store.dispatch(loadUser());
}
componentDidUpdate(nextProps) {
if (nextProps.user !== this.props.user) {
this.setState({ email: this.props.user});
}
}
state = {
userName: "",
password: "",
passwordConfirm: "",
email: "",
msg: null
}
static propTypes = {
isAuthenticated: PropTypes.bool,
setPass: PropTypes.bool,
register: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
user : PropTypes.object.isRequired,
};
onSubmit = (e) => {
e.preventDefault();
const {password, userName, email} = this.state
const setPass = {
password, userName, email
}
this.props.setPass(setPass);
const {passwordConfirm} = e.target;
const errors = {};
if (password.value !== passwordConfirm.value) {
errors.passwordMismatch = "Entered passwords do not match.";
console.log(errors)
}
}
onChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
};
render() {
return (
<div className={"container"}>
<div className={"row row-of-final-register justify-content-center"}>
<div className={"mt-5 register-teacher-inputs-box final-register-teacher-inputs-box"}>
<div className={"final-register-wrapper"}>
<form className={"mt-5"} onSubmit={this.onSubmit}>
<div className={"row"}>
<div className={"col-12"}>
<label
htmlFor={"userName"} className={"text-right username-label"}>
<span>*</span>
</label>
<input type="text" className="form-control w-100" placeholder={"Username"}
name={"userName"}
autoComplete="true"
value={this.userName}
onChange={this.onChange}
onFocus={(e) => e.target.placeholder = ""}
/>
</div>
</div>
<div className={"row"}>
<div className={"col-12 col-lg-6 mt-3"}>
<label
htmlFor={"password"} className={" text-right"}>
<span>*</span>
</label>
<input type="password" className="form-control " placeholder={"Password"}
name={"password"}
value={this.password}
onChange={this.onChange}
onFocus={(e) => e.target.placeholder = ""}
/>
</div>
</div>
<div className={"row mt-3 pt-2"}>
<div className={"col-12 final-register-wrapper final-register-btn"}>
<button type={"submit"} className={"final-register-btn"}>Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
)
}
}
function mapStateToProps (state , ownProperties) {
console.log(state.auth.user)
return {
setPass: state.auth.setPass,
isAuthenticated: state.auth.isAuthenticated,
error: state.error,
auth: state.auth,
user : state.auth.user,
}
};
function mapDispatchToProps(dispatch) {
return bindActionCreators(actionCreators, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps
)(RegisterFinal);
When run I have this data in my email state :
But when I try to access email get Error that cannot read property ‘email’ of undefined, I just change email : this.props.user to email : this.props.user.email in componentDidUpdate. I actually need to set redux props to react state. I'm new in redux.
Here share my project : my project
Here is a working example that will async load a user, set the initial value of a textbox with it's value and submit changes:
const { Provider, connect } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const { createSelector } = Reselect;
const initialState = {
user: null,
loading: true, //initially set loading to true
};
//helper for async
const later = (value) =>
new Promise((resolve) =>
setTimeout(() => resolve(value), 2000)
);
//action types
const CHANGE_USER = 'CHANGE_USER';
const CHANGED_USER = 'CHANGED_USER';
const LOAD_USER = 'LOAD_USER';
const LOADED_USER = 'LOADED_USER';
//action creators
const loadUser = () => ({
type: LOAD_USER,
});
const loadedUser = (user) => ({
type: LOADED_USER,
payload: user,
});
const changeUser = () => ({
type: CHANGE_USER,
});
const changedUser = (user) => ({
type: CHANGED_USER,
payload: user,
});
// action thunks
const loadUserThunk = () => (dispatch) => {
dispatch(loadUser());
return later({
email: 'original-email',
}).then((user) => dispatch(loadedUser(user)));
};
const changeUserThunk = (email) => (dispatch) => {
dispatch(changeUser());
return later({
email,
}).then((user) => dispatch(changedUser(user)));
};
const reducer = (state, { type, payload }) => {
if (type === LOAD_USER || type === CHANGE_USER) {
return { ...state, loading: true };
}
if (type === LOADED_USER || type === CHANGED_USER) {
return {
...state,
user: payload,
loading: false,
};
}
return state;
};
//selectors
const selectUser = (state) => state.user;
const selectLoading = (state) => state.loading;
const selectUserEmail = createSelector(
[selectUser],
//want to use user?.email but SO babel is too old
(user) => user && user.email
);
//creating store with redux dev tools
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducer,
initialState,
composeEnhancers(
applyMiddleware(
({ getState, dispatch }) =>
(next) =>
(
action //simple thunk implementation
) =>
typeof action === 'function'
? action(dispatch, getState)
: next(action)
)
)
);
class App extends React.PureComponent {
state = {
email: '',
initial: true, //only initially set from redux
};
componentDidUpdate() {
if (!this.props.loading && this.state.initial) {
this.setState({
email: this.props.email,
initial: false,
});
}
}
//arrow function so you don't need to bind for "this" context
onSubmit = (e) => {
e.preventDefault();
this.props.dispatch(changeUserThunk(this.state.email));
//reset initial
this.setState({ initial: true });
};
emailChanged = (e) =>
this.setState({ email: e.target.value });
componentDidMount() {
this.props.dispatch(loadUserThunk());
}
render() {
return (
<form onSubmit={this.onSubmit}>
<input
type="text"
onChange={this.emailChanged}
value={this.state.email}
// do not edit when loading
disabled={this.props.loading}
/>
<input type="submit" />
{this.props.loading && 'loading...'}
</form>
);
}
}
//do not use store in your components, connect will provide
// dispatch on this.props when mapDispatchToProps is
// undefined or you can pass an object as mapDispatchToProps
const ConnectedApp = connect((state) => ({
email: selectUserEmail(state), //select state.user.email as props.email
loading: selectLoading(state),
}))(App);
ReactDOM.render(
<Provider store={store}>
<ConnectedApp />
</Provider>,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>
<div id="root"></div>

setState into store component

I have to set a value on from a API into a newly created <button> component handled by Redux, but I don't know if I can use setState for this. I created a reducer and an action SET_VOTE_COUNT but I'm not seeing how this is done. This is my first Redux project, so here is the code:
// ./src/js/components/CounterList.js
import React from 'react';
import { connect } from 'react-redux';
import { increment, decrement } from '../actions/reducer';
import Counter from './Counter';
const CounterList = ({
counters,
onIncrement,
onDecrement
}) => (
<ul>
{counters.map(counter =>
<Counter style={{div: "voting"}}
key={counter.id}
value={counter.count}
onIncrement={() => onIncrement(counter.id)}
onDecrement={() => onDecrement(counter.id)}
/>
)}
</ul>
);
const mapStateToProps = (state) => {
return {
counters: state
};
};
const mapDispatchToProps = (dispatch) => {
return {
onIncrement: (id) => dispatch(increment(id)),
onDecrement: (id) => dispatch(decrement(id))
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(CounterList);
// ./src/js/components/Counter.js
import React, { Component } from 'react';
class Counter extends Component {
render() {
return (
<div className="voting">
<span>{this.props.value}</span>
<button
onClick={() => this.props.onIncrement()}>
+
</button>
<button
onClick={() => this.props.onDecrement()}>
-
</button>
</div>
);
}
}
export default Counter;
import React, {Component} from 'react';
import logo from '../../logo.svg';
import '../../App.css';
import AddButton from './AddButton'
class Posts extends Component {
constructor(props) {
super(props);
this.state = {
response: ''
};
}
componentDidMount() {
fetch(
"/posts"
).then(response => response.json())
.then(data => this.setState({ response: data }))
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
{Array.isArray(this.state.response) &&
this.state.response.map(resIndex => <>
{ resIndex.voteScore}
<AddButton className="voting"/>
<p> { resIndex.title }, by { resIndex.author } </p>
<p> { resIndex.body } </p>
<p> {resIndex.category} </p>
</>
)}
</header>
</div>
)
}
}
export default Posts;
import React from 'react';
import { add_counter, setVoteCount } from '../actions/reducer';
import { connect } from 'react-redux';
const AddButton = ({dispatch}) => (
<div className="voting">
<button
onClick={() => {
dispatch(setVoteCount())
// dispatch(add_counter());
}}>
Vote
</button>
</div>
);
export default connect()(AddButton);
The reducer:
// ./src/js/actions/counters.js
export const setVoteCount = (id) => {
return {
type: "SET_VOTE_COUNT",
id
};
}
export const increment = (id) => {
return {
type: "INCREMENT",
id
};
};
export const decrement = (id) => {
return {
type: "DECREMENT",
id
};
};
export const add_counter = () => {
return {
type: "ADD_COUNTER"
};
};
store action:
import { createStore, applyMiddleware, compose } from 'redux';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const change_counter = (state = {}, action) => {
switch (action.type) {
case "SET_VOTE_COUNT":
if (state.id !== action.id) {
return state;
}
return {
...state,
count : 37
}
case "INCREMENT":
if (state.id !== action.id) {
return state;
}
return {
...state,
count: state.count+1
};
case "DECREMENT":
if (state.id !== action.id) {
return state;
}
return {
...state,
count: state.count - 1
};
default:
return state;
}
};
let nextId = 0;
const counters = (state = [], action) => {
switch (action.type) {
case "ADD_COUNTER":
return [...state, {id: nextId++, count: 0}];
case "SET_VOTE_COUNT":
return [...state, {id: nextId++, count: action.count}];
case "INCREMENT":
return state.map(counter => change_counter(counter, action));
case "DECREMENT":
return state.map(counter => change_counter(counter, action));
default:
return state;
}
}
export default createStore(counters, composeEnhancers(applyMiddleware()));
I can upload it to GitHub if necessary. Many thanks.
In the AddButton component,the actions should be wrapped in mapDispatchToProps and passed to the connect function. You are calling the raw action in your example, but you need to wrap it with dispatch for it to update the store.
However, I'm not sure what you are trying to update the store with exactly. The action payload is empty in your example, and the reducer has 37 hardcoded as the state.count in response the SET_VOTE_COUNT action type. Did you mean to pass something from the API response?
<AddButton count={resIndex.count} className="voting"/>
import React from 'react';
import { add_counter, setVoteCount } from '../actions/reducer';
import { connect } from 'react-redux';
const mapDispatchToProps = {
setVoteCount
};
const AddButton = props => (
<div className="voting">
<button onClick={() => {
props.setVoteCount(props.count);
}}>
Vote
</button>
</div>
);
export default connect(null, mapDispatchToProps)(AddButton);

How to pass object to Redux

I would like ask you about passing object to Redux.
Below is my code.
// src/actions/writingType.js
export const write = () => ({
type: 'WRITE',
})
export const update = (obj) => ({
type: 'UPDATE',
obj
})
// src/reducers/writingType.js
const initialState = {
writingType: "WRITE",
obj: null
}
const writingTypeReducer = (state = initialState, action) => {
console.log('\n inside writingTypeReducer');
console.log(action);
switch (action.type) {
case 'WRITE':
return {
...state,
writingType: 'WRITE'
};
case 'UPDATE':
return {
...state,
writingType: 'UPDATE',
obj: action.obj
};
default:
return state;
}
}
export default writingTypeReducer;
// Contentview.js
import React, { useContext } from 'react';
import { Route, Link } from 'react-router-dom';
import MarkdownRenderer from 'react-markdown-renderer';
import './Contentview.css';
import { connect } from 'react-redux'
import { write, update } from '../../actions/writingType'
import { UserConsumer } from '../../contexts/userContext';
import { Test } from '../../contexts/Test';
const Contentview = (props) => {
/*
category: "React"
contentObj:
contents: "something"
createdDatetime: "2019.10.26 08:52:05"
title: "something"
wikiIndex: 1
*/
console.log('\n Contentview');
console.log(props);
console.log('\n update(props.contentObj);');
update(props.contentObj);
const url = "/editor/" + props.category;
const updateUrl = "/update/" + props.category;
return (
<div>
<div className="categoryDiv">{props.category}</div>
<div className="writingDiv"><Link to={url}> A </Link></div>
<div className="updateDiv"><Link to={updateUrl} > B </Link></div>
<hr />
<MarkdownRenderer markdown={props.contentObj.contents} />
</div>
);
};
// export default Contentview;
const mapStateToProps = (state, props) => ({
writetypestate: state.writingType,
obj: props.contentObj
})
const mapDispatchToProps = dispatch => ({
write: () => dispatch(write()),
update: (obj) => {
console.log('Contentview, mapDispatchToProps, update');
dispatch(update(obj))
}
})
export default connect(mapStateToProps, mapDispatchToProps)(Contentview)
I used update(props.contentObj); in Contentview.js to pass props.contentObj to Redux and update obj of initialState in src/reducers/writingType.js. But obj of initialState hasn't changed and existed as null.
How should I change code?
Thank you.
use props.update to call in the main file
// Contentview.js
import React, { useContext } from 'react';
import { Route, Link } from 'react-router-dom';
import MarkdownRenderer from 'react-markdown-renderer';
import './Contentview.css';
import { connect } from 'react-redux'
import { write, update } from '../../actions/writingType'
import { UserConsumer } from '../../contexts/userContext';
import { Test } from '../../contexts/Test';
const Contentview = (props) => {
/*
category: "React"
contentObj:
contents: "something"
createdDatetime: "2019.10.26 08:52:05"
title: "something"
wikiIndex: 1
*/
console.log('\n Contentview');
console.log(props);
console.log('\n update(props.contentObj);');
props.update(props.contentObj);
const url = "/editor/" + props.category;
const updateUrl = "/update/" + props.category;
return (
<div>
<div className="categoryDiv">{props.category}</div>
<div className="writingDiv"><Link to={url}> A </Link></div>
<div className="updateDiv"><Link to={updateUrl} > B </Link></div>
<hr />
<MarkdownRenderer markdown={props.contentObj.contents} />
</div>
);
};
// export default Contentview;
const mapStateToProps = (state, props) => ({
writetypestate: state.writingType,
obj: props.contentObj
})
const mapDispatchToProps = dispatch => ({
write: () => dispatch(write()),
update: (obj) => {
console.log('Contentview, mapDispatchToProps, update');
dispatch(update(obj))
}
})
export default connect(mapStateToProps, mapDispatchToProps)(Contentview)
Please use the above code

Failed to setup loader in react-component

I am trying to setup a loader. But the code is never going through the if blocks.
import React from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import LoadingPage from './LoadingPage';
import { usersFetchData, addFollower, addFollowing, removeFollower,
removeFollowing, resetUser} from '../actions/users';
class UserProfile extends React.Component{
constructor(props){
super(props);
this.state = {
isFollowed: false,
content: undefined
}
}
componentDidMount(){
this.props.fetchData(`http://localhost:5000/api/user/
${this.props.match.params.uid}`);
(Object.keys(this.props.user).length !== 0) &&
(this.props.user.followers.includes(this.props.currentUser.uid)) &&
this.setState({isFollowed: true});
}
openContentModal = (post) => {
this.setState({content:post});
console.log(this.state);
}
closeContentModal = () =>{
this.setState(() => ({ content: undefined }));
console.log(this.state);
}
render(){
if (this.props.hasErrored) {
return <p>Sorry! There was an error loading the items</p>;
}
if (this.props.isLoading) {
console.log('loading...');
return <LoadingPage />;
}
console.log(this.props.isLoading);
return(
<div className="userProfile">
<div>
{console.log(this.props.user)}
{ Object.keys(this.props.user).length !== 0 &&
<div className="user__details">
<div className="user__dp">
<div className="dp__container">
<img src={this.props.user.avatar} alt=
{this.props.user.name}/>
</div>
</div>
<div className="user__description">
<p className="user__name">
{this.props.user.name}</p>
<div className="user__button">
{(this.props.currentUser.uid ===
this.props.user.uid) ?
</div>
</div>
</div>
}
</div>
<div className="user__bio">
<p>{this.props.user.bio}</p>
</div>
<div>
{/* <h3>Posts</h3> */}
<div className="userContent">
{this.props.user.posts &&
this.props.user.posts.map((post) =>{
return(
<div className="userPost">
<Link to=
{`/p/${this.props.user.name}/${post._id}`}>
<img src={post.content}/></Link>
</div>
);
})
}
</div>
</div>
</div>
)
}
}
const mapStateToProps = (state) =>{
console.log(state.usersIsLoading); //getting undefined
return{
currentUser: state.auth,
user: state.users,
hasErrored: state.usersHasErrored,
isLoading: state.usersIsLoading
}
};
const mapDispatchToProps = (dispatch) => {
return {
fetchData: (url) => dispatch(usersFetchData(url))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(UserProfile);
Action
export const userIsLoading = (bool) => ({
type: 'USER_IS_LOADING',
isLoading: bool
});
export const usersFetchDataSuccess = (users) => ({
type: 'USERS_FETCH_DATA_SUCCESS',
users
});
export const usersFetchData = (url) => {
return (dispatch) => {
dispatch(userIsLoading(true));
console.log('hi');
axios
.get(url)
.then(res => {
if(!res){
throw Error(res.statusText)
}
dispatch(userIsLoading(false));
console.log(res.data);
return res.data;
})
.then(users => {
console.log('users',users);
dispatch(usersFetchDataSuccess(users))
})
.catch(() => dispatch(userHasErrored(true)));
}
}
reducer
export const userIsLoading = (state = false, action) => {
switch (action.type) {
case 'USER_IS_LOADING':{
return action.isLoading;
}
default:
return state;
}
}
export const users = (state = {}, action) => {
switch (action.type) {
case 'USERS_FETCH_DATA_SUCCESS':{
return action.users;
}
i have consoled the state. then i am getting a valid boolean value from userIsLoading. But when i am consoling the state.userIsLoading, I am getting undefined. This is very peculiar.can anyone tell me where am i getting it wrong?

Resources