1

I have just started learning React and I'm trying to make a simple application for searching vacancies using third-party server API. The application consists of form with one input, on submit it sends a request to server using axios, gets a response and must render it.

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import "bootstrap/dist/css/bootstrap.css";
import axios from 'axios';

const instance = axios.create({
  baseURL: 'https://api.hh.ru/vacancies/',
  headers: {
        'User-Agent': 'React App/1.0 ([email protected])', 
        'HH-User-Agent': 'React App/1.0 ([email protected])'
    }
});

const Header = () => {
    return <h1>Поиск вакансий на HH.ru</h1>
}

const Vacancies = props => {
    return <div>Some Text</div>
}

class SearchForm extends React.Component {
    constructor(props) {
        super(props)

        this.state = {
            position: ''
        }

        this.handlePositionChange = this.handlePositionChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handlePositionChange(e) {
            this.setState({
                [e.target.name]: e.target.value
            });
        }

    handleSubmit(e) {
        e.preventDefault();

        var formButton = document.getElementById('form-button');
        formButton.disabled = true;

        var position = this.state.position;
        console.log(position);

        if ( position ) {
            instance({
                    method: 'GET',
                    url: '?text=' + position,
                    data: {
                        position: position
                    }
                })
                .then(function(response) {
                    console.log(response.data);
                    formButton.disabled = false;
            })
               .catch(function (error) {
                console.log(error);
              });
        } else {
            formButton.disabled = false;
        }
    }

    render() {
        return (
            <form className="form search-form" onSubmit = { this.handleSubmit }>
                <div className="form-row">
                    <div className="form-group col-md-8">
                        <label htmlFor="position"> Position *
                            < /label>
                                <input type="text" className="form-control" name="position" id="position" placeholder="Position" onChange={ this.handlePositionChange } value={ this.state.position } />
                    </div>

                    <div className="form-group col-md-4 d-flex flex-column justify-content-end">
                        <input id = 'form-button'
                        className = 'btn btn-primary'
                        type = 'submit'
                        placeholder = 'Send' / >
                    </div>
                </div>
            </form>
        )
    }
}

class App extends Component {
  render() {
    return (
      <div className="container">
        <div className="row">
            <div className="col-12">
                <Header />
                <SearchForm />
                <Vacancies />
            </div>
        </div>
      </div>
    );
  }
}

export default App;

I have a problem with rendering <Vacancies />, is it possible to render it dynamically and update data every time on every new request and response from server?

1 Answer 1

2

What you want is for Vacancies to get the updated data which is what you get after an API request from SearchForm, in such a case you need to restructure your components and Lift the action up in the parent and pass the data as props to the Sibling components

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import "bootstrap/dist/css/bootstrap.css";
import axios from 'axios';

const instance = axios.create({
  baseURL: 'https://api.hh.ru/vacancies/',
  headers: {
        'User-Agent': 'React App/1.0 ([email protected])', 
        'HH-User-Agent': 'React App/1.0 ([email protected])'
    }
});

const Header = () => {
    return <h1>Поиск вакансий на HH.ru</h1>
}

const Vacancies = props => {
    return <div>Some Text</div>
}

class SearchForm extends React.Component {
    constructor(props) {
        super(props)

        this.state = {
            position: ''
        }

        this.handlePositionChange = this.handlePositionChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handlePositionChange(e) {
            this.setState({
                [e.target.name]: e.target.value
            });
        }

    render() {
        return (
            <form className="form search-form" onSubmit = { (e) => this.handleSubmit(e, this.state.position) }>
                <div className="form-row">
                    <div className="form-group col-md-8">
                        <label htmlFor="position"> Position *
                            < /label>
                                <input type="text" className="form-control" name="position" id="position" placeholder="Position" onChange={ this.handlePositionChange } value={ this.state.position } />
                    </div>

                    <div className="form-group col-md-4 d-flex flex-column justify-content-end">
                        <input id = 'form-button'
                        className = 'btn btn-primary'
                        type = 'submit'
                        disabled={this.props.disableSubmit}
                        placeholder = 'Send' / >
                    </div>
                </div>
            </form>
        )
    }
}

class App extends Component {
      state = {
        disableSubmit: false;
      }
      handleSubmit = (e, position) => {
        e.preventDefault();

        this.setState({disableSubmit : true});
        console.log(position);

        if ( position ) {
            instance({
                    method: 'GET',
                    url: '?text=' + position,
                    data: {
                        position: position
                    }
                })
                .then(function(response) {
                    this.setState({data: response.data, disableSubmit:false});
            })
               .catch(function (error) {
                console.log(error);
              });
        } else {
            this.setState({disableSubmit : false});
        }
    }
  render() {
    return (
      <div className="container">
        <div className="row">
            <div className="col-12">
                <Header />
                <SearchForm handleSubmit = {this.handleSubmit} disableSubmit={this.state.disableSubmit}/>
                <Vacancies data={this.state.data}/>
            </div>
        </div>
      </div>
    );
  }
}

export default App;

Also while using React you must make sure that you are not modifying the DOM element yourself and handle all Interactions the React way. For instance you can control the disabled state of your submit button using a prop or a state.

Sign up to request clarification or add additional context in comments.

2 Comments

It's hard to understand for me, why the component can't contain all its logic itself and why logic must be placed in component's parent. I used to OOP classes with all their data and logic inside. But anyway thanks for explanation!
@Heidel, I think react docs are a good place to know how to handle different scenarios, for a start you could look at reactjs.org/docs/lifting-state-up.html. Also check this answer stackoverflow.com/questions/46594900/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.