polar
polar

Reputation: 522

Classless react states?

Im trying to build a simple app with react-boilerplate, the containers(basically views) and components do not use classes to create new components, instead they are basic functions. Typically you add a constructor or direct state to a class, since there are no classes i dont know where to add the state definition. Nowhere ive added a constructer or state definition works, where can you add simple react (NO redux) state list or constructor within this pattern for this view?

example of a container

/*
 * HomePage
 *
 * This is the first thing users see of our App, at the '/' route
 */

import React, { useEffect, memo } from 'react';
import PropTypes from 'prop-types';
import { Helmet } from 'react-helmet';
import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { createStructuredSelector } from 'reselect';

import { useInjectReducer } from 'utils/injectReducer';
import { useInjectSaga } from 'utils/injectSaga';
import {
  makeSelectRepos,
  makeSelectLoading,
  makeSelectError,

} from 'containers/App/selectors';
import H2 from 'components/H2';
import ReposList from 'components/ReposList';
import AtPrefix from './AtPrefix';
import CenteredSection from './CenteredSection';
import Form from './Form';
import Input from './Input';
import Section from './Section';
import messages from './messages';
import { loadRepos } from '../App/actions';
import { changeUsername, setHomeVisible } from './actions';
import { makeSelectUsername, makeHomeVisible } from './selectors';
import reducer from './reducer';
import saga from './saga';
import NavBar from './NavBar';
import ButtonLink from './ButtonLink';

const key = 'home';

export function HomePage({
  username,
  loading,
  error,
  repos,
  onSubmitForm,
  onChangeUsername,
  homeVisible,
  makeHomeVisible,
  setHomeVisible
}) {
  useInjectReducer({ key, reducer });
  useInjectSaga({ key, saga });

  useEffect(() => {
    // When initial state username is not null, submit the form to load repos
    if (username && username.trim().length > 0) onSubmitForm();
  }, []);

  const reposListProps = {
    loading,
    error,
    repos,
  };

  return (
    <article>
      <Helmet>
        <title>title</title>
        <meta
          name="description"
          content=""
        />
      </Helmet>
      <NavBar>
        <ButtonLink to="/" onClick={makeHomeVisible}>
          <FormattedMessage {...messages.websites} />
        </ButtonLink>
        <ButtonLink to="/apps" >
          <FormattedMessage {...messages.apps} />
        </ButtonLink>
      </NavBar>
      <div className={`home ${this.state.visible === false ? 'hidden': ''}`}>
        <Section>
          <H2>
            <FormattedMessage {...messages.trymeHeader} />
          </H2>
          <Form onSubmit={onSubmitForm}>
            <label htmlFor="username">
              <FormattedMessage {...messages.trymeMessage} />
              <AtPrefix>
                <FormattedMessage {...messages.trymeAtPrefix} />
              </AtPrefix>
              <Input
                id="username"
                type="text"
                placeholder="mxstbr"
                value={username}
                onChange={onChangeUsername}
              />
            </label>
          </Form>
          <ReposList {...reposListProps} />
        </Section>
      </div>
    </article>
  );
}

HomePage.propTypes = {
  loading: PropTypes.bool,
  homeVisible: PropTypes.bool,
  error: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]),
  repos: PropTypes.oneOfType([PropTypes.array, PropTypes.bool]),
  onSubmitForm: PropTypes.func,
  username: PropTypes.string,
  onChangeUsername: PropTypes.func,
  makeHomeVisible: PropTypes.func,
};

const mapStateToProps = createStructuredSelector({
  repos: makeSelectRepos(),
  username: makeSelectUsername(),
  loading: makeSelectLoading(),
  error: makeSelectError(),
  homeVisible: makeHomeVisible(),
});

export function mapDispatchToProps(dispatch) {
  return {
    onChangeUsername: evt => dispatch(changeUsername(evt.target.value)),
    makeHomeVisible: evt => dispatch(setHomeVisible(evt.target.value)),
    onSubmitForm: evt => {
      if (evt !== undefined && evt.preventDefault) evt.preventDefault();
      dispatch(loadRepos());
    },
  };
}

const withConnect = connect(
  mapStateToProps,
  mapDispatchToProps,
);

export default compose(
  withConnect,
  memo,
)(HomePage);

Upvotes: 0

Views: 440

Answers (1)

Samuel Goldenbaum
Samuel Goldenbaum

Reputation: 18909

As per the React Docs, you can use the useState hook to save data to state. There is no "state list or constructor" but you can simply access the props you pass in and decide to save those into state if they are going to be manipulated - if not stick to using the props.

Codesandbox Demo

Basic Example:

function Child(props) {
  let [name, setName] = useState(props.data.name);

  function updateName () {
    setName('The Dude');
  }
   return (
    <div className="App">
     <h2>{name}</h2>
     <button onClick={updateName}>Update</button>
    </div>
  );
};

function App() {
  let [data, setData] = useState({name: 'dude'});
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <Child data={data}/>
    </div>
  );
}

Upvotes: 1

Related Questions