В приложении React-Redux не работает функция поиска - PullRequest
1 голос
/ 01 августа 2020

Я новичок в сокращении (и переполнении стека), и у меня есть некоторые проблемы с моей функцией поиска. Первоначально он отлично работал с данными, которые я установил вручную, но затем я импортировал данные из API, и теперь я не могу заставить поиск работать. Мы будем очень благодарны за любую помощь или совет!

<- actions -> //fetchData.js

import {
    FETCH_DATA_REQUEST,
    FETCH_DATA_SUCCESS,
    FETCH_DATA_FAILURE,
    SEARCH_POSTS
} from './types';

export const fetchData = () => {
    return (dispatch) => {
        dispatch(fetchDataRequest())
        axios
            .get("https://hn.algolia.com/api/v1/search?query=redux")
            .then(response => {
                const posts = response.data
                dispatch(fetchDataSuccess(posts))
            })
            .catch(error => {
                dispatch(fetchDataFailure(error.message))
            })
    }
}

export const fetchDataRequest = () => {
    return {
        type: FETCH_DATA_REQUEST
    }
}

const fetchDataSuccess = posts => {
    return {
        type: FETCH_DATA_SUCCESS,
        payload: posts
    }
}

const fetchDataFailure = error => {
    return {
        type: FETCH_DATA_FAILURE,
        payload: error
    }
}
  

export function searchData(value) {
    return {
        type: SEARCH_POSTS,
        payload: value
    }
}

<--- components ---> // dataContainer . js

import { connect } from 'react-redux';
import { fetchData } from '../actions/fetchData';
import { Card } from 'react-bootstrap';
import { Button } from 'react-bootstrap';

function DataContainer({ results, fetchData }) {
    useEffect(() => {
        fetchData()
    }, [])
    return results.loading ? (
        <h2>Loading...</h2>
    ) : results.error ? (
        <h2>{results.error}</h2>
    ) : (
                <div>
                    <h1>Posts</h1>
                    {results && results.posts && results.posts.map(result =>
                        <div className ="cardDiv" key={result.objectID}>
                            <Card>
                                <Card.Header>By: {result.author}</Card.Header>
                                <Card.Body>
                                    <Card.Title>{result.title}</Card.Title>
                                    <Card.Text>
                                        {result.body}
                                    </Card.Text>
                                    <Button variant="primary" href={result.url}>See Article</Button>
                                </Card.Body>
                            </Card>
                            {'\n'}
                        </div>)}
                </div>
            )
}

const mapStateToProps = state => {
    return {
        results: state.data
    }
}

const mapDispatchToProps = dispatch => {
    return {
        fetchData: () => dispatch(fetchData())
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(DataContainer);

// searchBar. js

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { searchData, fetchData } from '../actions/fetchData';

function SearchBar({ posts, fetchData}) {
    useEffect(() => {
        fetchData()
    }, [])

    const { search, value } = posts;

    return (
        <input
            className="form-control mx-auto"
            placeholder="Search"
            onChange={(e) => searchData(e.target.value)}
            value={value}
            style={{ maxWidth: '200px', textAlign: 'center' }} />
    );
}

function mapStateToProps({ posts, state }) {
    return {
        posts: state.posts,
        value: posts.value
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({ searchData, fetchData }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(SearchBar);

// homePage. js

import SearchBar from './searchBar';
import DataContainer from './dataContainer';
import { connect } from 'react-redux';
import * as actions from '../actions/fetchData';

class HomePage extends Component {

  handleSearchBarSubmit(query) {
      this.props.fetchPostsWithQuery(query, () => {
        this.props.history.push('/results');
      });

  }

  render() {
    return (
      <div className="home">
        <SearchBar page="home"/>
        <DataContainer/>
      </div>
    );
  }
}

export default connect(null, actions)(HomePage);

<--- Редукторы ---> // dataReducer

    FETCH_DATA_REQUEST,
    FETCH_DATA_SUCCESS,
    FETCH_DATA_FAILURE,
    SEARCH_POSTS
} from "../actions/types";
const _ = require('lodash')

const posts = []

const initState = {
    loading: false,
    posts,
    error: '',
    filtered: []
}

const reducer = (state = initState, action) => {
    switch (action.type) {
        case FETCH_DATA_REQUEST:
            return {
                ...state,
                loading: true
            }
        case FETCH_DATA_SUCCESS:
            return {
                loading: false,
                posts: action.payload.hits,
                filtered: action.payload.hits,
                error: ''
            }
        case FETCH_DATA_FAILURE:
            return {
                loading: false,
                posts: [],
                error: action.payload
            }
        case SEARCH_POSTS:
            const { payload } = action
            const filtered = _.filter(state.data.posts, (o) => _.toLower(o.post).includes(_.toLower(payload)))
            return {
                ...state,
                filtered
            }
        default: return state
    }
}

export default reducer;

// searchReducer. js

    SEARCH_POSTS
} from '../actions/types';

const posts = []

const INIT_STATE = {
   posts
}

export default function (state = INIT_STATE, action) {
    switch (action.type) {
        case SEARCH_POSTS: {
            let { value } = action.payload.hits;
            const posts = state.posts.filter((post) => post.title.toLowerCase().includes(state.value.toLowerCase()));
            return { ...state, value, posts };
        }
        default:
            return state;
    }

}

// rootReducer. js

import { combineReducers } from 'redux';
import { reducer as form } from 'redux-form'
import resultsPosts from './searchReducer';

const rootReducer = combineReducers({
    data: dataReducer,
    resultsPosts,
    form
})


export default rootReducer;

<- - Приложение js и индекс. js ---> //app.js

import './App.css';
import HomePage from './components/homePage';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import ResultPage from './components/resultPage'

function App() {
  return (
    <BrowserRouter>
      <div className='App'>
        <h1 style={{textAlign: 'center'}}>Search for Hacker News!</h1>
        <Switch>
          <Route path="/" exact={true} component={HomePage} />
          <Route path='/results/:id' component={ResultPage}/>
        </Switch>
      </div>
    </BrowserRouter>
  );
}

export default App;

// index. js

import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { Provider } from 'react-redux';
import store from './store';


ReactDOM.render(
  <Provider store={store}>
  <App />
  </Provider>,
  document.getElementById('root')
);

serviceWorker.unregister();
...